$ ruby -e "A=1; p A /1"
-e:1: unterminated regexp meets end of file
スラッシュが割り算の演算子ではなく正規表現を見なされてエラーになるようです。
ここで、Aを小文字にして、定数から変数に変えてやると、
$ ruby -e "a=1; p a /1"
1
となり、今度は割り算の演算子に解釈されているようです。どうしてこのような動作になるのか、説明をお願いします。
逆ポーランド記法といって
式の右側から解釈されるためです
下の本に書いてありました
まつもとゆきひろ コードの世界?スーパー・プログラマになる14の思考法
コメント(8件)
手元に古いのがあるんですが、それだと両方とも同じエラーになります。
ruby 1.6.7 (2002-04-11) [i386-mingw32]
で再現できました。
詳しくは調べていませんのでコメントで書きます。おそらく、文脈で意味が変わったため解釈に変化が生じ、異なる結果が得られたのではないでしょうか。
a = 1 によって a が変数であり、式の一部だとみなされて、その後 / を見つけた、という流れだと思います。
定数 A の場合は / を見つけた途端正規表現リテラルの先頭文字であるとrubyが認識している(ruby -yで確認)のでエラーになります。a に代入しなかった場合も同じエラーが出ます。
% ruby -ve "p(a /1)"
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]
-e:1: warning: ambiguous first argument; put parentheses or even spaces
-e:1: unterminated string meets end of file
-e:1: syntax error, unexpected tSTRING_END, expecting tSTRING_CONTENT or tREGEXP_END or tSTRING_DBEG or tSTRING_DVAR
ちゃんと原因をご存じの方の回答を待ちたいところ。
環境という基本的なことを記述せず済みません。
バージョンは1.9.2です。以下がruby -vの出力結果です。
ruby 1.9.2p136 (2010-12-25 revision 30365) [x86_64-darwin10]
km1981>式の右側から解釈されるためです
ちげーよ。
parser レベルの挙動じゃん。
想像でしか無いんですが、こういうコンパイラみたいに文脈を解釈するプログラムでは、
字句解析 → 構文解析 という二段階で行われます。
字句解析のレベルのエラーになると思うんですが、古いバージョンだと、
変数と定数の違いで挙動に変化が無いので、
文法の拡張 or 解析の高速化のために parser (字句解析をするやつ) の実装が変わったんでしょうね。
定数のときだけだから、最適化がらみかなあ...
○: $A=1; p $A /1 グローバルにしてみた
○: A=1; p A/1 / の前の空白を削った
×: A=1; p (A /1) "A /1" で、ひとかたまりだよ、って教えたつもり
×: A=1; p "#{A /1}" 同じく...
・上の方は'A'をメソッド名と解釈するから、次の'/'を正規表現リテラルの開始と解釈している
・下の方は'a'を変数名と解釈するから、次の'/'を演算子と解釈している
ということだと思います。
で、知りたいのはなぜ'A'と'a'の解釈が異なるかということだと思いますが、わかりません(-o-;
言語開発者達が、括弧を省略した時にこう解釈した方が自然だろうと考えたとしか…
以下、構文解析の結果です。
> ruby -rripper -rpp -e "pp Ripper.sexp('A=1; p A /1')"
[:program,
[[:assign, [:var_field, [:@const, "A", [1, 0]]], [:@int, "1", [1, 2]]],
[:command,
[:@ident, "p", [1, 5]],
[[:command,
[:@const, "A", [1, 7]],
[:args_add_block,
[[:regexp_literal, [], [:@regexp_end, "1", [0, 10]]]],
false]]]]]]
> ruby -rripper -rpp -e "pp Ripper.sexp('a=1; p a /1')"
[:program,
[[:assign, [:var_field, [:@ident, "a", [1, 0]]], [:@int, "1", [1, 2]]],
[:command,
[:@ident, "p", [1, 5]],
[:args_add_block,
[[:binary, [:var_ref, [:@ident, "a", [1, 7]]], :/, [:@int, "1", [1, 10]]]],
false]]]]
http://webcache.googleusercontent.com/search?q=cache:ubeJV5k9-ooJ:www.ruby-lang.org/ja/man/html/ruby_1_7_feature.html+Ruby+1.7+%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE&hl=ja&ie=UTF-8
--------------------------------------------------
2002-11-08
[parser] [experimental]
実験的な修正のようです。
a = 1
p a / 5
=> ruby 1.6.8 (2002-12-24) [i586-linux]
0
=> ruby 1.8.0 (2003-03-12) [i586-linux]
0
a = 1
p a /5
=> -:2: warning: ambiguous first argument; make sure
-:2: unterminated regexp meets end of file
ruby 1.6.8 (2002-12-24) [i586-linux]
=> ruby 1.8.0 (2003-03-12) [i586-linux]
0
2002-11-02
Object#object_id
--------------------------------------------------
実験的な修正で、変数は処理するようにしたけど定数が置いてかれたといった
ところでしょうか。
コメントされた方にはポイントをお分けすることができずすみません。