[ruby-list:50742] Re: 割り算と正規表現リテラル

From: "Masa Sakano" <imagine@...>
Date: 2019-01-24 13:18:15 UTC
List: ruby-list #50742
坂野正明です。

これは、パースの問題ですね。
「/」は、Rubyデフォルトの有名どころで、除算、整除、正規表現の開始および終了、という
少なくとも4つの演算子の意味があります。加えて、ユーザーが(再)定義可能です。
正規表現の開始演算子、と解釈された場合、文は、そのあとの複数行にまたがることが許されます。

p foo /10

の場合、これは、

p(foo/10)  # 
「foo÷10」の返り値を表示して、p()の結果を返す
p(foo)/10  # 「foo」の返り値を表示して、「p(foo)」÷10 
の結果を返す
p(foo /10  # 
正規表現の後ろ側をプログラム最後まで探す → 
存在しないので、エラー
p(foo) /10 # 
正規表現の後ろ側がプログラム最後まで探す → 
存在しないので、エラー

の4つの可能性があり得ます。
加えれば、それぞれに、foo 
がインスタンス変数かメソッドかの二つの可能性があります。
(いずれも、それ以前の文のパースから、"p"が文の始まりである、と判断された時、という条件のもと。)

Ruby 
のパースは恐ろしく賢くて、一番それらしいものを賢く選ぶことが普通ですが、
それでも元の文があまりに不明瞭だと、エラーや警告が出ます。

(多くの人間の期待と一致するだろう)例として、

p foo/10   # => p(foo/10) と解釈
p foo / 10 # => p(foo/10) と解釈

のように解釈されます。
ここで、特に 
2番目の例の場合、本来は、そう解釈されなくてはならないとは必ずしも限らなくて、
「p(foo)/10」のように解釈される可能性はありそうなものですが、
Ruby(少なくともRuby2)のパースはそれを避けているようです。

なお、"foo"の部分がリテラルの数字の場合に限っては、数字に続く「/」は、前後の空白のある無しに関わらず
除算(または整除)記号とパーサーは解釈するようですね。だから、
p 50 /10
は、「p(50/10)」と解釈されるようです。

ご投稿のケースでは、Rubyのパーサーが賢すぎて、パースの原則が一貫してないように見えたのが、
混乱を呼んだ一因でしょうか。

結論として、ご質問に一言で答えるならば、それは「Rubyの現在の仕様」と言ってよいでしょう。


Rubyコードを書く時には、紛らわしい書き方はなるべく避けるべきなのが鉄則だと理解しています。
でないと、Rubyのパーサーの判断と、プログラマーの判断が異なることはあり得ます!

具体的には、p() 
文の場合、表示させる内容には、一切空白を入れずに書くのが原則だと理解しています。
例: 「p foo/10」

空白を入れたい場合は、「p(foo / 
10)」のように、陽に括弧を入れるべきです。
そうすると、紛れがありませんから。

ご参考までに。

坂野正明

On 24 Jan 2019, at 12:33, OOTANI TAKASHI wrote:

> 大谷ともうします。
>
> def foo
>     100
> end
>
> p foo
> p foo /10
>
> が、/ 
> の後に空白を置かないと、もしくは、foo()にしないと、
> unterminated regexp meets end of file のエラーになるのは、
> 仕様でしょうか?バグでしょうか?
> メソッドの引数とみなされてしまうようですね。
>
> エラーにならないケースだと、
>
> def foo(arg=nil)
>     100
> end
> i=10
>
> p foo
> p foo /10
> p foo /i
>
> とか。
>
> -- 
> tksotn

In This Thread