Variables 在评估一个条件后,如何在球拍中设置一个变量
我在评估状态后设置球拍变量时遇到问题。如果我有一个函数定义,比如Variables 在评估一个条件后,如何在球拍中设置一个变量,variables,binding,scheme,racket,Variables,Binding,Scheme,Racket,我在评估状态后设置球拍变量时遇到问题。如果我有一个函数定义,比如 (define foo (lambda (x y z) (cond ((> 3 2) (what code here?))))) 假设我想将变量z设置为值10,如果条件的计算结果为true,那么语法是什么?在Scheme中,我们设置如下变量: (set! z 10) 。。。但这是不受欢迎的,通常你要不惜一切代价避免变异状态。记住,Scheme的核心是一种函数式编程语言;必须有更好的
(define foo
(lambda (x y z)
(cond
((> 3 2)
(what code here?)))))
假设我想将变量z设置为值10,如果条件的计算结果为true,那么语法是什么?在Scheme中,我们设置如下变量:
(set! z 10)
。。。但这是不受欢迎的,通常你要不惜一切代价避免变异状态。记住,Scheme的核心是一种函数式编程语言;必须有更好的方法来完成您试图完成的任务,而不改变变量的值。最可能的情况是,您希望使用z
参数的新值调用递归:
(foo x y 10)
正如其他海报所说,在racket中使用这种命令式的编程风格是一种不好的做法。尽管如此,但这并不意味着这件事做不到!第一次尝试将其作为函数执行时,可能会出现以下情况:
(define (setter variable condition value)
(if condition (begin (set! variable value) variable) variable))
(define a 10)
(setter a #t 5)
a
运行此函数将返回5和10。这就是我们开始看到函数的词法范围的地方。变量总是在其作用域中定义的,这是一个很好的系统,允许我们使用“list”作为函数参数的名称,尽管list是racket中的函数。Racket将假定您指的是当前范围中定义的变量,并覆盖以前的变量
基本上,我们希望(set!variable value)
调用发生在我们关心的范围内,即setter函数之外。请注意:
a(set!a10)a
返回10 5,表示它做了我们想要的事情。嗯,如果我们传递一个真实的条件,那么现在只要我们能使setter真正成为code(set!variable value)
。这将把它放在期望的范围内
我们可以!这就是球拍的宏观系统发挥作用的地方。在Racket(以及scheme和lisp语言)中,您编写的程序是数据,就像数字和布尔值一样,这意味着您可以操纵它们并返回新值
(define-syntax-rule (setter variable condition value)
(if condition (begin (set! variable value) variable) variable))
现在,塞特做了我们想要的
(define a 10)
a
(setter a #t 5)
a
正确返回10 5 5。简而言之,宏非常棒。请参阅球拍指南,了解一些关于如何使用它们以及它们可以做什么的优秀教程 通常,您避免修改Racket(和Scheme)中变量的值。通过这样做,最好询问您想要解决的问题,而不是您心目中的特定解决方案。因为Racket具有词法范围,所以
z
的范围是foo
的内部范围。因此,在运行foo
之后,无法访问z
,名称和值都消失了。事实上还有更多的故事,因为编译器会将z
压缩成一个唯一的符号,以避免全局变量名出现某种类型的错误。@benrudgers这很有意义,谢谢。谢谢您的详细解释。我不打算在Racket(或Scheme)中做很多工作,但宏听起来正是我需要考虑的。