Functional programming 球拍中定义错误
几天前我刚刚发现了Racket,我正试图通过编写一个小脚本来更轻松地使用它,该脚本使用Functional programming 球拍中定义错误,functional-programming,lisp,scheme,expression,racket,Functional Programming,Lisp,Scheme,Expression,Racket,几天前我刚刚发现了Racket,我正试图通过编写一个小脚本来更轻松地使用它,该脚本使用#lang slideshow生成图像来表示源代码 我知道,在函数范式中编程时,使用let创建几乎所有变量是一种很好的做法,但我发现它引入了太多层次的嵌套,而且Racket's let的API过于复杂,需要多余的括号。我确信这是为了在以更强大的方式使用let时消除歧义,但就我而言,这只是一个麻烦。因此,我使用define创建所有变量,并在需要时使用begin编写块(例如在if语句体中) 问题是,我不断地犯下一些
#lang slideshow
生成图像来表示源代码
我知道,在函数范式中编程时,使用let
创建几乎所有变量是一种很好的做法,但我发现它引入了太多层次的嵌套,而且Racket's let的API过于复杂,需要多余的括号。我确信这是为了在以更强大的方式使用let
时消除歧义,但就我而言,这只是一个麻烦。因此,我使用define
创建所有变量,并在需要时使用begin
编写块(例如在if
语句体中)
问题是,我不断地犯下一些看起来很神秘的错误。我确信我只是犯了一些愚蠢的初学者错误,对这门语言还不熟悉,但我似乎真的找不到抱怨的根源
以下是违规代码:
(define sub-code (foldr ht-append (rectangle 0 0) (map internal-style (rest code))))
虽然我们所定义的子代码似乎不相关。如果我用
(define sub-code '())
我收到了同样的错误。DrRacket表示define
正在表达式上下文中使用。我理解这个错误通常意味着什么——也就是说,当你编写像(print(define x 10))
这样的代码时,它会出现,但我看不出是什么触发了它
如果有帮助,则此定义
位于开始
块的开头,在If
语句中
(if (list? code)
(begin
(define sub-code '())
; a few more define statements and finally an expression ))
DrRacket正在打印的特定错误消息为
define: not allowed in an expression context in: (define sub-code (quote ()))
我想在begin
块中可能不允许define
,但是我检查了begin
的一个示例是
(begin
(define x 10)
x)
所以我真的不知道该怎么办。提前谢谢 定义可以在“body”上下文中使用,如
lambda
和let
等。if
的结果从句和替代从句不是主体上下文;它们是表达式上下文,因此不允许使用定义
begin
是特殊的-begin
在主体上下文中允许定义,但表达式上下文中的begin
禁止定义。你的案子交给后者处理
例如:
(define (foo . args) #| body context #|)
(define foo (lambda args #| body context |#))
(define (foo . args)
(let (...)
#| body context |#))
需要表达式的语法关键字:if、cond、case和,或、when、除非、do、begin
。检查任何Scheme报告中的正式语法(r{4,5,6,7}rs);查找
、
、
和
此外,如果您需要表达式中的主体上下文,只需包装一个let
语法形式,如下所示:
(if test
(let ()
(define foo 'foo)
(list foo foo))
alternate)
正如GoZoner所解释的,您不能在表达式上下文中使用
define
你能做些什么呢
使用让
:
(if (list? code)
(let ([x '()])
x)
...
或者它将与一个“空的”let
和define
:
(if (list? code)
(let ()
(define x '())
x)
...
(cond [(list? code)
(define x '())
x]
...
但这有点傻
或者使用cond
和define
:
(if (list? code)
(let ()
(define x '())
x)
...
(cond [(list? code)
(define x '())
x]
...
最后一种方法——使用
cond
和define
——与推荐的方法最接近。以下是来自Racket文档的更多详细信息
之所以需要,是因为宏的展开方式必须不同,这取决于允许的语言形式
正如其他人所说,在表达式上下文(“文档中的expr…”)中不允许定义,但在其他上下文中可以定义
在其他文档条目中,“body…”表示内部定义上下文(,),例如在lambda body中,“form…”表示所有非表达式上下文,如begin文档中。或者您可以将表达式包装在(begin)中 e、 g.(开始) (定义x10) (定义y 100)
(define z 1000))
cond
不建立表达式上下文(根据我在R6RS和R7RS草案规范中的测试)。在Racket中(cond[#t(define x 1)x])
有效并返回1
。我们都知道……Racket不是Scheme…:-)在Ikarus(cond(#t(define foo'foo)(list foo foo))
->“错误:在需要表达式的位置找到了定义。”谢谢!最后只使用了let
,但是知道begin
可以这样隐式变形是很有用的。我的直觉是(begin foo)
只是((lambda()foo))
的简写,但我想它比这更复杂。