kenketsuの日記: 代入演算子 4
色々なプログラミング言語の代入演算子(CやJavaだと=)が戻り値を持つことを知らない人が結構いる。自分の場合は、昔それに気付いた時に「なるほどっ!!」と思った覚えがある。つまり、代入「演算子」と呼ばれる理由が納得できたということ。
ただ、なぜ変数に値を代入する操作に戻り値があるのか…と真正面から問われたならば、自分は答えに詰まるかもしれない。
すぐ思いつく例は、x = y = 1;のように代入を繋げる時や、以下のような感じ(これはJavaっぽい謎言語)で代入と条件判定を一行で書けるよね、というもの。でもこれだと、なぜという疑問への回答にはなっていない。仕様を便利に使おうというだけだから。
String str = null;
while ((str = readLine(in)) != null) {
...
}
四則演算やビット演算などの明確な結果を戻す演算子と比べると、代入演算子はなぜそういう仕様なのかが直感しづらい気がする。演算子の一つとしての一貫性を保つためかもしれないけれど、それでも何かモヤモヤするものがある。
「そういうものだ」と教条主義になってしまっては何か負けた気がするし、なぜかを知りたいと思っている人に「こういうことだ!!」と胸を張って伝えられない気がする。今のところ、自分としての答えはないのが口惜しい。
それはともかく、プログラミング言語は評価(evaluation)の連続だということを、プログラミングの初心者であればこそ身に着けて欲しいし、粘り強く教えてあげたい。そうでないと、プログラムが動く仕組みが分からないし、プログラミング言語に使われているという立場から脱却できないと思う。
それに、プログラムを動かすということは高い目線で見ると定義と評価の塊であって、そういうことが分かっていないと関数型プログラミング言語がなぜイケているのかが分からないと思うのだよね。
むしろ戻り値のない演算(サブルーチン)が邪道である (スコア:1)
戻り値のない(戻り値がvoid型と言っても良いが)演算の方がおかしいと考えれば解決。
あるオブジェクトに戻り値がvoid型のメソッド(サブルーチン)を実装したくなったら、常に自分自身を返すメソッドとして実装することを考えるべきだ。
そうすれば
objA.mathod1().method2().method3() とメソッドチェーンで書けるのだ。
代入演算子に戻り値があるのは、あって然るべきなのだ。ない方がおかしいのだ。
Re:むしろ戻り値のない演算(サブルーチン)が邪道である (スコア:1)
コメントどうもです。
演算には必ず戻り値があるべき、という観点には同意します。他の方のコメントにもあった通り、演算子としての仕様の一貫性という面からは正しいことだと思います。
一方、論点がずれるかもしれないことを承知で書きますが、メソッドチェーンができるようデザインすべきかは、そのクラスの役割によるかと思います。
私の理解ではメソッドチェーンは冗長な記述を避けるためのイディオムの一つという印象が強く、メソッドの戻り値をvoidではなく常にthisとすべきかどうかとは観点が別だと思うのです。
ただ、これは私がJavaをメインに使っていて、演算子オーバーロードの機能があるC++やRubyなどの視点に慣れていないからかもしれません。しかし、Rubyでも代入演算子はオーバーロード出来ないのです。
変数が指すインスタンスを変更するのが代入演算子の役割であって、それをメソッドとして実装するとはどういうことなのだろうか、しかもその戻り値とは…と考えていくと、少し混乱してきてしまいます。どうも私も勉強が足りないようですね。
仕様 (スコア:0)
仕様を決めるときに「便利に使えるうえに一貫性が保てる」というのはそれだけで十分な理由になりえると思うんだけど。
Re:仕様 (スコア:1)
コメントありがとうございます。
いえ、つい最近にプログラミングの初心者へ「代入演算子は演算の一つで、戻り値があるんだよ」と伝えたところ、「?」という顔をされてしまいました。
「便利に使える上に一貫性が保てる」という説明もしたのですが、通じなかったようなのです。
ですので、そういう事を考えた上での仕様だと言う他に、何かグッとくる、グサッと刺さる理由はないかなと考えていたのです。