11

如何在方案中通过引用传递变量?

我想要的功能示例:

(define foo
  (lambda (&x)
    (set! x 5)))

(define y 2)

(foo y)

(display y) ;outputs: 5

另外,有没有办法通过引用返回?

4

7 回答 7

12

请参阅http://community.schemewiki.org/?scheme-faq-language问题“有没有办法模拟 call-by-reference?”。

总的来说,我认为这与方案的功能性质作斗争,因此可能有更好的方法来构建程序以使其更像方案。

于 2010-07-16T05:33:30.563 回答
4

就像 Jari 所说,通常您希望避免在 Scheme 中通过引用传递,因为它表明您正在滥用副作用。

但是,如果你愿意,你可以将任何你想通过引用传递的东西放在一个cons盒子里。

(cons 5 (void))

将产生一个包含 5 的框。如果您将此框传递给将 5 更改为 6 的过程,则您的原始框也将包含 6。当然,您必须记住cons何时car合适。

Chez Scheme(以及可能的其他实现)有一个称为box(及其同伴box?unbox)的过程,专门用于这种装箱/拆箱废话:http ://www.scheme.com/csug8/objects.html#./objects:s43

于 2010-07-16T05:40:05.207 回答
4

您可以使用宏:

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
于 2012-01-25T05:01:07.327 回答
2

拉姆达!

(define (foo getx setx)
  (setx (+ (getx) 5)))

(define y 2)
(display y)(newline)

(foo
 (lambda () y)
 (lambda (val) (set! y val)))

(display y)(newline)
于 2010-07-16T15:52:22.663 回答
2

Jari 是对的,通过引用传递有点不合时宜,至少对于变量来说是这样。然而,你想要的行为一直被使用,并且经常被鼓励,通过使用闭包以更像方案的方式。经验丰富的方案中的第 181 页和第 182 页(谷歌图书)做得比我能解释的要好。

这是一个参考,它提供了一个宏,允许您使用类似 ac 的语法来“通过引用传递”。Olegs 网站是有趣阅读的金矿,因此如果您还没有,请务必将其标记为书签。

http://okmij.org/ftp/Scheme/pointer-as-closure.txt

于 2010-07-16T20:17:30.550 回答
2

您可以从外部上下文中定义的函数内影响外部上下文,这使您可以通过引用变量获得影响,即具有副作用的函数。

(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解决方案相同。

于 2014-10-29T07:09:34.293 回答
0

你可能使用了太多的 C、PHP 或其他东西。在方案中,您不想做诸如 pass-by-* 之类的事情。首先了解范围的含义以及不同实现的行为方式(特别是尝试找出 LISP 和 Scheme 之间的区别)。

本质上,纯函数式编程语言没有副作用。因此,这意味着 pass-by-ref 不是一个功能概念。

于 2010-07-16T11:43:23.533 回答