Functional programming 球拍中定义错误

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语句体中) 问题是,我不断地犯下一些

几天前我刚刚发现了Racket,我正试图通过编写一个小脚本来更轻松地使用它,该脚本使用
#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))
的简写,但我想它比这更复杂。