5

RacketまたはSchemeのとまたはvalueslist違いは何ですか? consどちらか一方を使用する方が良いのはいつですか?たとえば、 ?ではなくquotient/remainderreturnの場合の欠点は何でしょうか?(cons _ _)(values _ _)

4

4 に答える 4

7

2002 年に、George Caswell が comp.lang.scheme でその質問をしました。次のスレッドは長いですが、多くの洞察があります。議論は、意見が分かれていることを明らかにします。

https://groups.google.com/d/msg/comp.lang.scheme/ruhDvI9utVc/786ztruIUNYJ

当時の私の答え:

>    What are the motivations behind Scheme's multiple return values feature?
> Is it meant to reflect the difference in intent, or is there a
> runtime-practical reason?

I imagine the reason being this.

Let's say that need f is called by g. g needs several values from f.
Without multiple value return, f packs the values in a list (or vector),
which is passed to g. g then immediately unpacks the list.

With multple values, the values are just pushed on the stack. Thus no
packing and unpacking is done.

Whether this should be called an optimization hack or not, is up to you.

--
Jens Axel Søgaard

We don't need no side-effecting         We don't need no allocation
We don't need no flow control           We don't need no special-nodes
No global variables for execution       No dark bit-flipping for debugging
Hey! did you leave the args alone?      Hey! did you leave those bits alone?
(Chorus)                  -- "Another Glitch in the Call", a la Pink Floyd
于 2015-04-09T16:50:55.767 に答える
4

これらは、Scheme と Racket で意味的に同じです。どちらの場合でも、リターンを使用するには、リターンがどのように見えるかを知る必要があります。

valuesに接続されcall-with-values、特殊な形式のようなものlet-valuesは、このプロシージャ コールのシンタックス シュガーにすぎません。ユーザーは、結果を利用するために使用する結果の形式を知る必要がありますcall-with-values。多くの場合、リターンはスタック上で行われ、呼び出しもスタック上にあります。スキームを優先する唯一の理由valuesは、プロデューサーのリターンとコンシューマーの呼び出しの間にオーバーヘッドがないことです。

cons(または) を使用するとlist、ユーザーは戻り値のデータ構造がどのように見えるかを知る必要があります。同様に、同じことをする代わりにvalues使用できます。(およびその他)の代替として、マクロを作成するのは簡単です。applycall-with-valueslet-valuesdestructuring-bind

Common Lisp では、まったく異なります。提供する情報がさらにある場合はいつでも値を使用でき、ユーザーが最初の値のみを使用したい場合は、通常の手順として使用できます。quotientしたがって、CL の場合、同様に機能するため、バリアントとして提供する必要はありませんquotient/remainder。複数の値を取る特殊なフォームまたはプロシージャを使用する場合にのみ、プロシージャがより多くの値を返すという事実は、Scheme と同じように機能します。これはvalues、Scheme よりも CL の方が適しています。これは、複数のプロシージャーを作成する代わりに 1 つのプロシージャーを作成するだけで済むためです。

CL では、次のようにハッシュにアクセスできます。

(gethash 'key *hash* 't)
; ==> T; NIL

返された 2 番目の値を使用しないと、T がデフォルト値なのか実際に見つかった値なのかわかりません。ここでは、ハッシュでキーが見つからなかったことを示す 2 番目の値が表示されます。多くの場合、数値しかないことがわかっている場合は、デフォルト値がすでにキーが見つからなかったことを示しているため、その値を使用しません。ラケットで:

(hash-ref hash 'key #t)
; ==> #t

ラケットfailure-resultではサンクになる可能性があるので大丈夫ですが、値がCLのように機能した場合は、代わりに複数の値が返されるに違いありません。CLバージョンとSchemeにはより多くのハウスキーピングがあると思います.Schemeは最小限の言語であるため、おそらく実装者に余分な作業を与えたくありませんでした.

于 2015-04-09T14:07:36.393 に答える
4

編集:これを投稿する前に、同じトピックに関するAlexisのコメントを見逃しました

リストよりも複数の戻り値を使用することの見過ごされがちな実用的な利点の 1 つは、Racket がcompose複数の値を返す関数で「そのまま動作する」ことです。

(define (hello-goodbye name)
  (values (format "Hello ~a! " name)
          (format "Goodbye ~a." name)))

(define short-conversation (compose string-append hello-goodbye))

> (short-conversation "John")
"Hello John! Goodbye John."

によって生成される関数は、 によってcompose返された 2 つの値hello-goodbyeを 2 つの引数としてに渡しますstring-append。多くのコンポジションを持つ関数型スタイルでコードを書いている場合、これは非常に便利で、などで値を明示的に渡すよりもはるかに自然ですcall-with-values

于 2015-04-10T03:28:40.310 に答える