プログラミング言語Rubyに関する質問です。次のようにスラッシュの直後に空白文字を入れずに書くと、


$ ruby -e "A=1; p A /1"
-e:1: unterminated regexp meets end of file

スラッシュが割り算の演算子ではなく正規表現を見なされてエラーになるようです。
ここで、Aを小文字にして、定数から変数に変えてやると、

$ ruby -e "a=1; p a /1"
1

となり、今度は割り算の演算子に解釈されているようです。どうしてこのような動作になるのか、説明をお願いします。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2011/07/28 08:32:38
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答1件)

id:km1981 No.1

回答回数429ベストアンサー獲得回数49

ポイント200pt

逆ポーランド記法といって

式の右側から解釈されるためです

下の本に書いてありました

  • id:a-kuma3
    使ってる ruby のバージョンは何でしょう?
    手元に古いのがあるんですが、それだと両方とも同じエラーになります。

    ruby 1.6.7 (2002-04-11) [i386-mingw32]
  • id:Mook
    1.8.6 では質問のような現象になりますね。
  • id:iwadon
    ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]
    で再現できました。

    詳しくは調べていませんのでコメントで書きます。おそらく、文脈で意味が変わったため解釈に変化が生じ、異なる結果が得られたのではないでしょうか。
    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

    ちゃんと原因をご存じの方の回答を待ちたいところ。
  • id:suginoy
    質問者です。
    環境という基本的なことを記述せず済みません。
    バージョンは1.9.2です。以下がruby -vの出力結果です。

    ruby 1.9.2p136 (2010-12-25 revision 30365) [x86_64-darwin10]
  • id:a-kuma3
    km1981>逆ポーランド記法といって
    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}"   同じく... 
  • id:Bookmarker
    # たぶん期待している回答ではないと思うのでコメントで。

    ・上の方は'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]]]]
  • id:Mook
    キャッシュしか残っていませんでしたが、「ruby 1.7 feature」に下記の記載がありました。
    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
    --------------------------------------------------

    実験的な修正で、変数は処理するようにしたけど定数が置いてかれたといった
    ところでしょうか。
  • id:suginoy
    Matzが意図した仕様なのかはわかりませんが、とても勉強になりました。
    コメントされた方にはポイントをお分けすることができずすみません。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません