VBScriptで書かれた以下のコードと等価なRubyコードは何でしょうか?
a = b = c
答え
そのコードが書かれているコンテキストによって、以下の2つのどちらかになる。
a = (b == c)
(a == b) == c
VBScriptは代入と比較の両方を1つの演算子 =
でまかないます。
また、VBScriptは代入は式ではなく文です。
そのため、代入と比較の演算子が別々になっている言語を学んだ人がVBScriptを使うと、予想だにしない挙動に遭遇することがあります。
多くの言語では、程度にもよりますが、式と文の境界が曖昧になっており、式が要求されそうなコンテキストに文を書くことができます。
厳密に言うならば、はある言語では文として提供されている機能が、別の言語では式として提供されているということです。
Rubyは他の言語では文として提供されている多くのものが式になっていますので、サンプルとして適切です。
# ifは文ではなく式
a = (if hoge == fuga then 1 else 0 end)
# メソッド定義ですら式になる
a = (def hoge; end)
ifやメソッド定義すらも式になるというRubyの仕様はJavaプログラマーなどからすると異質なものに見えます。
これらまで式にするのはやりすぎだという意見もあるかもしれません。
しかし、はるか昔に文から式になったものを私たちは受け入れ、なんの違和感もなくそれを式として扱っています。
それが代入です。
以下のコードが実行できるのは代入が式として扱われていることの証拠です。
もし、代入が文であるならば、その結果をaに代入することはできないからです。
a = b = c
しかし、VBScriptでは代入は式ではなく文です。
a = b = c
の両方の=を代入にすることはできません。
そのため、VBScriptの a = b = c
と等価なRubyコードは a = (b == c)
もしくは (a == b) == c
です。
可能性は2つあります。
どのようなときに前者と解釈され、どのようなときに後者と解釈されるのでしょうか?
ここでもまた、代入は式ではなく文という仕様を思い出します。
前者は式ですが、後者は文です。
つまり、このコードが書かれたコンテキストが文が要求されるものなのか、式が要求されるものなのかによって、どちらになるのかが決まります。
' 式が要求されるコンテキスト
Call Func(a = b = c)
While a = b = c
' 文が要求されるコンテキスト
a = b = c