天泣記

2014-12-12 (Fri)

#1

もしかすると、Ruby に16進小数を入れても実際的な非互換性は生じないのかもしれない。

16進小数というのは 0x123.456 みたいなものである。

16進なので a-f も使えて、0xabc.def みたいなこともできる。

16進小数の利点は、浮動小数点数を正確かつコンパクトに表現できることである。IEEE754 の浮動小数点の仮数部は 2進数なので、これを桁を合わせて 16進にしたものが 16進小数で、浮動小数点数を正確に指定したいというときに役に立つ。

ここで問題になるのが、現在 0xabc.def は 0xabc という整数 (2278) に対する def メソッドの呼び出しとして解釈されるので、これを 16進小数として解釈する (0xabcdef / (16**3).to_f つまり約2748.8708) と、意味が変わってしまうので非互換になる、という点である。

この非互換性は実際に問題になるだろうか。

まず、現在 Integer クラスには 16進数に使える文字 ( 0-9a-fA-F に加えて区切りの意味で _ も使える) だけで構成されているメソッドは存在しない。

% ruby -e 'p Integer.instance_methods.reject {|n| /\A[0-9a-fA-F_]+\z/ !~ n.to_s }'
[]

しかし、Ruby では既存のクラスにメソッドを付け加えることができる (オープンクラス) ので、もしかしたら既存のコードが付け加えて使っているかもしれない。

そこで、既存の gem を全文検索してちょっと調べてみる。(1ヶ月くらい前に gem mirror して得た gem の各最新版を展開して milkode で全文検索できるようにしてある。)

% gmilk -s rb 0x|egrep '0x[0-9a-fA-F_]+\.[a-fA-F_][0-9a-fA-F_]*([^0-9a-zA-Z_]|$)'
Because number of records is large, Milkode use external tool. (Same as 'gmilk -e grep')
/extdisk/akr/ruby/rubygems/latest-gems/gnu_mpc-0.9.0/spec/atan_spec.rb:107:    expect(actual.imag).to eq GMP::F.new("-0x8.a7e33db93ecf18@-34", 57, 16)
/extdisk/akr/ruby/rubygems/latest-gems/metasm-1.0.1/tests/preprocessor.rb:263:              t_float['0x1.e4']

ひっかかったのは文字列の中だけなので、どうやら、16進小数とみなしうるコードは既存の gem の中にはないようである。

また、Ruby 2.1 から数値には i (虚数) と r (有理数) という suffix がつけられるようになったが、これらは a-f の範囲外なのでこれも衝突しない。

これは使えるようにしちゃってもいいのかもしれない。

2014-12-27 (Sat)

#1 test-unit の色の使い方はよくない

Ruby 2.2 から、(Ruby の外部で) require 'test/unit' とすると gem の test-unit が使われるようになって、しばらく使っていたのだが、どうも出力から素早く情報を読み取れない。

最初は慣れていないせいかな、と思っていたのだが、時間がたっても相変わらずで、これはたぶん出力が良くないのだということで、すこし真面目に考えてみた。

以下のテストを考える。

% cat tst.rb
require 'test/unit'

class C < Test::Unit::TestCase
  def test_a
    assert_equal(1, 2)
  end

  def test_b
    assert_equal(1, 1)
  end

  def test_c
    assert_equal(1, 3)
    raise
  end
end

これを Ruby 2.1 と Ruby 2.2 で比較してみた。

出力からまず読み取れる情報はまず個々の文字よりも大きな形や色である。というわけで、出力をぼかしてみてみよう。

Ruby 2.1 では以下のような結果になる。

result-210-blur.png

Ruby 2.2 では以下のような結果になる。

result-220-blur.png

これからいくつかのことがわかる。

テストが失敗した時には、たいていの場合、結局はぜんぶ直すわけだが、どのテストから直すかという選択は必要で、そのためにそれぞれの失敗を眺めることになる。そのときに、個々の失敗をすばやく認識できるとありがたい。Ruby 2.1 ではもっとも目立つ部分が失敗と対応していてそれが容易だったが、Ruby 2.2 ではもっとも目立つ部分は失敗と対応しなくなっていて、これはよくないと思う。結局のところ、テストの結果の表示は、失敗の並びなので、もっとも目立つ構造を個々の失敗が対応していないというのは結果の構造の認識を困難にしている

思うに、色の使い方はずいぶんと改善の余地があるのではないだろうか。

なお、ぼかさない結果は以下のようになる。

result-210.png

result-220.png

これをみると、Ruby 2.2 で出力が大きいのは、失敗した場所のソースを表示していること、予期された結果と実際の結果を 2回 (... expected but was ... と diff で) 表示しているのが原因である。

ソースの表示は、役に立つこともあるだろう。

結果を 2回表示しているのは、このケースではほぼ同じ情報を 2回表示しているだけで役に立っていない。役に立つ場合もあるのだろうが、役に立たない場合は表示しないでくれるとよいのだが。

考えた結果、個人的にもっとも気に入らないのは色の使い方で、失敗をすばやくみてとるのに不適切ということだと感じられる。

#2 test-unit の色の改善

と、書いたら、すとうさんがかなり直してくれて、以下のようになった。

result-latest.png

ここで目立っているものは以下の順だろう。

  1. 最後のサマリ行
  2. 失敗した行
  3. Failure

最後のサマリの行はユーザから見るといつもそこにあるので、ここまで目立たなくてもいいと思う。

失敗した行と Failure はどちらも失敗と対応している。どちらかが十分に目立てば、もっとも目立つものと失敗が対応することになる。

すとうさんは実際に失敗したところが気になるということなので、失敗した行のほうが目立つのは理にかなっているのだろう。

というわけで、その意図を進めるのであれば、サマリ行と Failure をもうちょっと目立たないようにするのがよいのではないか。

#3 端末における反転の使い方

結局、端末で反転 (文字の背景をデフォルトではない色にすること) はとても目立つため、いちばん目立ってほしいところに使うのは問題ないけれど、それ以外の場所に使うと(とくに使いすぎると)そっちが目立ってしまってよろしくない、という話なのだろう。


[latest]


田中哲