我怎么在Scheme中通过引用传递一个变量?
以下是我想要的功能示例:
(define foo
(lambda (&x)
(set! x 5)))
(define y 2)
(foo y)
(display y) ;outputs: 5
另外,有没有一种方法可以通过引用返回值?
我怎么在Scheme中通过引用传递一个变量?
以下是我想要的功能示例:
(define foo
(lambda (&x)
(set! x 5)))
(define y 2)
(foo y)
(display y) ;outputs: 5
另外,有没有一种方法可以通过引用返回值?
请查看http://community.schemewiki.org/?scheme-faq-language中的问题“是否有一种模拟按引用传递的方法?”。
总的来说,我认为这与Scheme的函数式本质相抵触,因此可能有更好的方法来构建程序,使其更符合Scheme的风格。
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))
使用 cons
进行封装后,会生成一个包含数字 5 的盒子。如果将此盒子传递给更改数字 5 为 6 的过程,则原始盒子也将包含数字 6。当然,在适当的时候需要记得使用 cons
和 car
。
在 Chez Scheme(以及其他一些实现)中,有一个称为 box
(以及其伴随的 box?
和 unbox
)的过程,专门用于这种封箱/解箱问题:http://www.scheme.com/csug8/objects.html#./objects:s43
lambda!
(define (foo getx setx)
(setx (+ (getx) 5)))
(define y 2)
(display y)(newline)
(foo
(lambda () y)
(lambda (val) (set! y val)))
(display y)(newline)
foo
接受两个参数,而不是一个)。 - gcbenison您可以从定义在外部上下文中的函数内部影响外部上下文,这使您具有按引用传递变量的影响,即具有副作用的函数。
(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
这个解决方案限制了副作用的范围。
否则,就像Eli在一个子评论中提到的那样,会出现(define x (box 5)), (unbox x)等问题,这与erjiang建议的cons解决方案相同。
你可能已经使用了太多的C、PHP或其他编程语言。
在Scheme中,你不想做像传递-by-*这样的事情。
首先要理解作用域的含义以及不同实现的行为(特别是试图弄清楚LISP和Scheme之间的区别)。
本质上,纯函数式编程语言没有副作用。因此,传递-by-ref不是一个函数式概念。
box
、unbox
和set-box!
的结果与在C语言中使用显式指针非常接近。虽然很少使用这种方法,但在某些情况下它确实有用——Scheme鼓励函数式编程并阻止突变,但并不完全反对这样做。(但在大多数情况下,这样做的新手代码可能需要重新思考。) - Eli Barzilay