[前][次][番号順一覧][スレッド一覧][生データ]

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]