スキームで変数を参照渡しするにはどうすればよいですか?
私が欲しい機能の例:
(define foo
(lambda (&x)
(set! x 5)))
(define y 2)
(foo y)
(display y) ;outputs: 5
また、参照で返す方法はありますか?
スキームで変数を参照渡しするにはどうすればよいですか?
私が欲しい機能の例:
(define foo
(lambda (&x)
(set! x 5)))
(define y 2)
(foo y)
(display y) ;outputs: 5
また、参照で返す方法はありますか?
http://community.schemewiki.org/?scheme-faq-languageの質問「call-by-reference をエミュレートする方法はありますか?」を参照してください。
一般に、それはスキームの機能的性質と戦うと思うので、プログラムをよりスキームに似たものにするためのより良い方法があると思います。
マクロを使用できます。
scheme@(guile-user)> (define-macro (foo var)`(set! ,var 5))
scheme@(guile-user)> (define y 2)
scheme@(guile-user)> (foo y)
scheme@(guile-user)> (display y)(newline)
5
Jari が言ったように、通常、副作用を悪用していることを示唆しているため、Scheme での参照渡しは避けたいと考えています。
ただし、必要に応じて、参照渡ししたいものをすべてcons
ボックスで囲むことができます。
(cons 5 (void))
このボックスを 5 を 6 に変更するプロシージャに渡すと、元のボックスにも 6 が含まれます。もちろん、必要に応じて を覚えておく必要がcons
ありcar
ます。
Chez スキーム (およびおそらく他の実装) には、このボクシング/アンボクシングのナンセンスのために特別に呼び出されたbox
(およびその仲間box?
と)という手順があります: http://www.scheme.com/csug8/objects.html#./objects:s43unbox
外部コンテキストで定義された関数内から外部コンテキストに影響を与えることができます。これにより、参照変数による受け渡しの効果が得られます。つまり、副作用のある関数です。
(define (outer-function)
(define referenced-var 0)
(define (fun-affects-outer-context) (set! referenced-var 12) (void))
;...
(fun-affects-outer-context)
(display referenced-var)
)
(outer-function) ; displays 12
このソリューションは、副作用の範囲を制限します。
それ以外の場合は、(define x (box 5))、(unbox x) などがあります。これは、Eli のサブコメントで言及されているもので、erjiang が提案するコンス ソリューションと同じです。
Jari が言うように、少なくとも変数を使用して参照渡しを行うのは、やや無謀です。ただし、必要な動作は、クロージャーを使用することにより、よりスキームのような方法で常に使用され、しばしば推奨されます。経験豊富なスキームの181ページと182ページ(グーグルブックス)は、私が説明できるよりも優れた仕事をしています.
これは、ac のような構文を使用して「参照渡し」できるようにするマクロを提供するリファレンスです。Olegs のサイトは興味深い読み物の宝庫なので、まだブックマークしていない場合はブックマークしておいてください。
ラムダ!
(define (foo getx setx)
(setx (+ (getx) 5)))
(define y 2)
(display y)(newline)
(foo
(lambda () y)
(lambda (val) (set! y val)))
(display y)(newline)
おそらく、CやPHPなどを使いすぎているでしょう。スキームでは、pass-by-*のようなことはしたくありません。まず、スコープの意味とさまざまな実装の動作を理解します(特に、LISPとSchemeの違いを理解してください)。
本質的に、純粋に関数型プログラミング言語には副作用はありません。したがって、pass-by-refは機能的な概念ではないことを意味します。