yarv-dev:279
From: MAEDA Atusi <maeda-yarv atusi.org>
Date: Tue, 2 Nov 2004 14:05:06 +0900
Subject: [yarv-dev:279] multivple values (Re: multiple assgin return value)
並列代入と多値は、いちおう分けて考えた方が良いのではないですか。
というわけでサブジェクト変更。
(ご参考)
Common Lispでは、以下のようなモデルになっています。
・関数は一般に複数(0個以上multiple-values-limit個未満)の値を返すことが
できる。 multiple-values-limitは処理系依存の定数(正の整数)で、少なく
とも20以上。たとえば、関数 FLOOR は、整数の除算を行ない、マイナス無
限大に向けて丸めた商と剰余を2つの値として返す。
ユーザ定義の関数から多値を返すには VALUES 関数を用いて、
(values 値1 値2 ...)
とする。
・一方、値を受けとる側には「多値aware」な文脈と、そうでない(1つの値し
か期待していない)文脈がある。多値aware(mvと呼ぶことにします)な文脈
は、専用の構文ではっきり区別される。
多値awareでない文脈(svと呼ぶことにします)で多値を受けとった場合、最
初の値だけが使われ、後は捨てられる。
(例) (+ (floor 5 3) (floor 19 4))
== (+ 1 4) => 5
(multiple-value-call #'+ (floor 5 3) (floor 19 4))
== (+ 1 2 4 3) => 10
svな文脈で「0個の値」を受けとると、NILを受けとったものとみなす。
(例) (print (values)) とすると副作用としてNILがプリントされる。
要するに、多値を意識しないプログラムは、「常に1個の値が返ってくる」と
思っていても何の不都合もない、と言うことです
Schemeでもvaluesで多値を返し、call-with-values構文を用いない限り多値を
受けとることは出来ない(一つの値だけを受けとる)のは同じですが、svな文脈
に1個以外の値を返すと、結果はunspecifiedです。(つまり、エラーになって
も仕方がないということ。)
Common Lisp風の多値を実装する方法もいろいろあると思いますが、例えばむ
かし私が考えたのはこんな感じです。
・VMには、「返した値の数」を表すレジスタnvaluesと、2番目以降の値を入れ
る配列(リストでもレジスタ群でも可)v[]を持つ。
・1個の値を返す時は、値をスタックトップに残し、nvaluesを1にセットする。
・VALUESや一部の組み込み関数は、nvaluesを1以外にセットし、v[]に必要な
値を入れる。nvaluesが0なら、最初の値としてNILを返す。
・他の関数が返した値をそのまま返す時は、nvaluesの数を変えないでreturn
する。
・svな文脈では、nvaluesなんかチェックせず、スタックトップの値だけ使う。
・mvな文脈では、nvaluesを見て、必要な値をv[]から取り出す。
コンパイラが式を処理する文脈として、式の位置に応じて、
・tail (この式の全ての値をそのままreturnする)
・sv (この式の最初の値だけを使う)
・mv (この式の全ての値を使う)
・nil (この式の値は使わない; 副作用のためだけに評価する)
と分類しました。例えば、
(defun fact (n)
(if (zerop n)
1
(progn
(print n)
(* n (fact (- n 1))))))
での各々の式の文脈は、
(if ...) → tail
1 → tail
(progn ...) → tail
(print n) → nil
(* ...) → tail
その他の式は、全てsvとなります。
多値を使わない場合のオーバーヘッドは、「tailの文脈で変数・定数・インラ
インした演算が表れた時、nvaluesを1にセットする」手間だけです。
他のやり方(多値を全てスタックに積んで返すとか)も考えられますが、オーバー
ヘッドはそう変わらないと思います。「1個の値を返した」ということは示さ
ないといけないので。
Yukihiro Matsumoto <matz ruby-lang.org> writes:
> 多値の実装の仕方は複数あると思います。
>
> * メソッドの戻り値を複数許す実装
>
> これが一番正統的なやり方でしょう。しかし、現在の実行モデ
> ルからは大幅に変化してしまいますね。
Common Lisp風にすれば、現在のプログラムはそのままで行けませんか?
> * 内部的なValuesオブジェクトを使う実装
>
> これだとメソッドの戻り値がひとつという枠組みのまま多値が
> 実現できます。現在のものはValuesオブジェクトがRuby世界に
> 見えてしまっていますが、代入の時にチェックすることで、
> 単値を要求されたときには最初の要素、多値が要求された時に
> は複数の値を与えることができます。代入のたびごとにチェッ
> クが発生しますから、オブジェクトのタイプはT_ARRAYではな
> く、T_VALUESのような別のものを導入した方が良いでしょうね。
svな文脈でも、返ってきたのが多値かどうかチェックするわけですよね。
多値を使わない場合のオーバーヘッドが気になります。
前田敦司
--
ML: yarv-dev quickml.atdot.net
使い方: http://www.atdot.net/~ko1/quickml
268 2004-11-01 19:28 [ko1 atdot.net ] multiple assgin return value 269 2004-11-01 19:56 ┗[matz ruby-lang.org ] 270 2004-11-02 05:27 ┗[ko1 atdot.net ] 271 2004-11-02 05:38 ┣[ko1 atdot.net ] 273 2004-11-02 08:01 ┃┗[matz ruby-lang.org ] 272 2004-11-02 08:00 ┣[matz ruby-lang.org ] 274 2004-11-02 08:15 ┃┗[ko1 atdot.net ] 275 2004-11-02 08:25 ┃ ┗[matz ruby-lang.org ] 276 2004-11-02 09:14 ┃ ┗[ko1 atdot.net ] 277 2004-11-02 09:36 ┃ ┗[matz ruby-lang.org ] -> 279 2004-11-02 14:05 ┃ ┣[maeda-yarv atusi.org] multivple values (Re: multiple assgin return value) 280 2004-11-02 14:49 ┃ ┃┗[matz ruby-lang.org ] 281 2004-11-02 17:54 ┃ ┃ ┣[maeda-yarv atusi.org] 282 2004-11-02 18:14 ┃ ┃ ┃┗[ko1 atdot.net ] 284 2004-11-02 19:37 ┃ ┃ ┃ ┗[maeda-yarv atusi.org] 283 2004-11-02 18:16 ┃ ┃ ┗[ko1 atdot.net ] 285 2004-11-02 19:47 ┃ ┃ ┣[matz ruby-lang.org ] 288 2004-11-02 20:43 ┃ ┃ ┃┗[ko1 atdot.net ] 289 2004-11-02 23:31 ┃ ┃ ┃ ┣[shugo ruby-lang.org ] 293 2004-11-03 08:35 ┃ ┃ ┃ ┃┗[ko1 atdot.net ] 290 2004-11-03 01:17 ┃ ┃ ┃ ┗[matz ruby-lang.org ] 291 2004-11-03 03:54 ┃ ┃ ┃ ┣[maeda-yarv atusi.org] 294 2004-11-03 08:57 ┃ ┃ ┃ ┃┗[matz ruby-lang.org ] 296 2004-11-03 11:58 ┃ ┃ ┃ ┃ ┗[maeda-yarv atusi.org] 298 2004-11-03 14:34 ┃ ┃ ┃ ┃ ┣[akr m17n.org ] 299 2004-11-03 15:39 ┃ ┃ ┃ ┃ ┃┗[maeda-yarv atusi.org] 315 2004-11-04 11:46 ┃ ┃ ┃ ┃ ┃ ┗[akr m17n.org ] 307 2004-11-04 01:49 ┃ ┃ ┃ ┃ ┗[matz ruby-lang.org ] 308 2004-11-04 02:08 ┃ ┃ ┃ ┃ ┗[shugo ruby-lang.org ] 310 2004-11-04 02:48 ┃ ┃ ┃ ┃ ┗[matz ruby-lang.org ] 292 2004-11-03 08:32 ┃ ┃ ┃ ┣[ko1 atdot.net ] 300 2004-11-03 17:36 ┃ ┃ ┃ ┃┣[matz ruby-lang.org ] 301 2004-11-03 22:19 ┃ ┃ ┃ ┃┃┗[ko1 atdot.net ] 304 2004-11-03 23:29 ┃ ┃ ┃ ┃┗[shugo ruby-lang.org ] 311 2004-11-04 02:56 ┃ ┃ ┃ ┃ ┗[ko1 atdot.net ] 312 2004-11-04 09:40 ┃ ┃ ┃ ┃ ┗[shugo ruby-lang.org ] 313 2004-11-04 09:45 ┃ ┃ ┃ ┃ ┗[ko1 atdot.net ] 314 2004-11-04 10:58 ┃ ┃ ┃ ┃ ┗[shugo ruby-lang.org ] 316 2004-11-04 12:48 ┃ ┃ ┃ ┃ ┗[ko1 atdot.net ] 295 2004-11-03 09:29 ┃ ┃ ┃ ┗[ko1 atdot.net ] 286 2004-11-02 20:05 ┃ ┃ ┗[maeda-yarv atusi.org] 287 2004-11-02 20:13 ┃ ┃ ┗[matz ruby-lang.org ] 302 2004-11-03 22:21 ┃ ┗[ko1 atdot.net ] 303 2004-11-03 22:54 ┃ ┗[matz ruby-lang.org ] 305 2004-11-03 23:31 ┃ ┗[ko1 atdot.net ] 306 2004-11-04 00:49 ┃ ┗[matz ruby-lang.org ] 278 2004-11-02 12:40 ┗[maeda-yarv atusi.org]