多値関数の議論

■[雑記/備忘]なぜ、多値関数は人気がないのだろう

次々に興味深い話題が。もう本当に片付けなきゃならないことが山程あるだろうって。

最初にこのエントリを読みながら思ったこととしては、

  • 多値を返す事ができる言語としては、Perl, Ruby, Python があるか。って、最近のスクリプト言語は大抵返せるってことか。
  • Emacs Lisp はできないけど、Common Lisp はできるみたいだ。あと Scheme も。
  • そもそも多重代入ができないと意味が無いのか。
  • 戻り値として返すことはそれ程面倒なことではなさそうだけど、多値を返す関数を考えたときに、その関数の使われる局面を考えると、あまり人間の思考に似わない気がするな。

といったところでした。

で、もう少し考えてみて、先ず最初の一つ目がおかしいことに気付きました。
そもそも Perl は引数にも戻り値にもリストが使えるというだけの話で、何れの場合でも引数は一つですね。文脈から、スカラーかリストかを判断しているに過ぎなかった筈。
更に多重代入も厳密には無い筈 (ですよね?) で、リストに放り込むということができるだけです。ここでもスカラとリストを文脈に応じて判断しています。

また、Ruby は values() によって多値が表現できるかの様に見せかけているだけですから、厳密には多値を返しているとは言えないのかもしれません。
;; まつもとさん自ら values() のことを「にせものの多値」と表現されていたり。
;; Ruby2 では多値を言語仕様に含む予定がある様ですが。
Python ではどうなんでしょう。values() を使うのは同じ様ですけど。

この辺り、何れもやってることは、引数の参照渡しの機構 (call-by-reference や call-by-name) を持たない C 言語の関数呼び出し機構に於ける擬似的な参照渡し (call-by-value でポインタを渡す) と似ていると思います。
一種のシンタックスシュガーでしょうか。

で、皆さんのコメントなどを拝見しながら少し調べてみると、プリミティブに多値に対応している Common LispScheme でも、実際に利用する際にはリストや配列を経由する必要がある様です。
※ 2006.02.13 shiro さんの指摘を受け削除しました。コメントを参照して下さい。
※ 以降の記述に影響がありそうなので、併せて変更が入るかもしれません。今のところはここを削除したのみです。

こうなると、厳密な戻り値の多値 (レジスタを複数使うとかスタックに複数の要素を積むとか) って必要なのかという気がしてきました。

そもそもの檜山さんの問い掛けでは、この様な意味で、引数との対称性という観点から、何故、戻り値には多値が無いのか? と考えておられると解釈しています。
その意味では、やはり上に挙げた幾つかの言語では、SchemeCommon Lisp でしか該当するものは無さそうですが、それでも結果的にはリストや配列を介してアクセスするのであれば、概念としては PerlRuby の仕組みも同じだという気もします。

そしてリストなどのデータ構造を介して複数の要素を返すことで用が足りるのであれば、Emacs Lisp でも C 言語でも同じことは可能な訳で、結局、殆どの言語で、サブルーチンの戻り値として複数の値 (多値) を返すことは可能と言えてしまう様に思えます。
あとはそれがスマートかとか、簡単かとか、そういう問題でしょうか。

必要かどうかということとはまた別に、対称性という意味では、ある関数の引数に別の関数の評価結果を指定する場合を考えてみます。
引数に指定された関数が多値を返す関数であると、それは複数の引数を表わすことになりますが、これが非常に悩ましいのだと思います。
実装云々よりも、セマンティクスとしてで、その様な構造が汎用的に可能なのは、

  • コレクションを返す関数
  • ある種の構造を返す関数

しか無い様に思います。
例えば例として挙げられている割り算の商と余りを返す多値関数ですが、これを他の関数の引数として指定することは無いだろうな、と。この様な関数は結果として代入式の右辺でしか使われず、とても使い辛い関数になってしまうのではないでしょうか。(とても手続き的な感じですね)
そういうものと割り切ってしまえば良いのかもしれませんけど。

私もなんだか考えるのがめんどくさくなってしまいました。(檜山さんの真似です。実は時間が無いのと頭がオーバーヒートしてるということです)
もう少し考えてみたいとは思うのですが、今日はここまででしょうか。

[追記]
最初の投稿でタイトルを失念してしまったために、トラックバックがちょっと変になってしまいました。
すみません、檜山さん。