12

几天前我刚刚发现了 Racket,我正在尝试通过编写一个小脚本来更熟悉它,该脚本生成图像以使用#lang slideshow.

我知道在函数范式中编程时,用 . 创建几乎所有变量是一种很好的做法let,但我发现它引入了太多的嵌套级别,并且 Racket 的 let 有一个过于复杂的 API,需要多余的括号。我确信这是为了let在以更强大的方式使用时消除歧义,但就我的目的而言,这只是一种烦恼。因此,我使用 , 创建所有变量define,并在需要时使用 编写块begin(例如在if语句的主体中)。

问题是我一再遇到看似非常神秘的错误。我确定我只是犯了一些愚蠢的初学者错误,对语言不熟悉,但我似乎真的找不到抱怨的根源。

这是有问题的代码:

(define sub-code (foldr ht-append (rectangle 0 0) (map internal-style (rest code))))

尽管我们定义sub-code的内容似乎无关紧要。如果我将其替换为

(define sub-code '())

我收到同样的错误。DrRacket 说的define是在表达式上下文中使用。我理解这个错误通常意味着什么 - 当你编写类似的代码时它会引发 IE (print (define x 10)),但我看不出是什么在这里触发它。

如果有帮助,这define是在一个begin块的开头,在一个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 ()))

我认为可能define不允许在begin块中,但我检查了文档,其中一个示例begin

(begin
    (define x 10)
    x)

所以我真的不知道该怎么办。提前致谢!

4

4 回答 4

15

允许在“主体”上下文中进行定义,例如 inlambdalet其他。的后续子句和替代子句if不是正文上下文;它们是表达式上下文,因此不允许定义。

begin是特殊的 -begin在正文上下文中允许定义,但begin在表达式上下文中禁止定义。你的案子属于后者。

例如:

(define (foo . args)     #| body context #|)
(define foo (lambda args #| body context |#))
(define (foo . args)
  (let (...)
    #| body context |#))

需要表达式的语法关键字:if, cond, case, and, or, when, unless, do, begin. 查看任何 Scheme 报告中的正式语法 (r{4,5,6,7}rs);寻找<body>, <sequence>,<command><expression>.

此外,如果您需要表达式中的正文上下文,只需包装一个let语法形式,如下所示:

(if test
    (let ()
      (define foo 'foo)
      (list foo foo))
    alternate)
于 2013-04-25T18:15:06.407 回答
8

正如 GoZoner 解释的那样,您不能define在表达式上下文中使用。

你能做什么呢?

使用let

(if (list? code)
    (let ([x '()])
      x)
    ...

或者它可以使用“空”let define

(if (list? code)
    (let ()
      (define x '())
      x)
    ...

但这有点傻。

或使用condand define

(cond [(list? code)
       (define x '())
       x]
      ...

最后一种方式——使用conddefine——最接近当前 Racket 风格指南推荐的方式。

于 2013-04-25T18:29:56.290 回答
4

这里有更多细节,来自 Racket 文档。

需要不同的上下文,因为宏必须以不同的方式扩展,具体取决于允许的语言形式。

正如其他人所说,表达式上下文中不允许定义(文档中的“expr ...”),但在其他上下文中可以。

在其他文档条目中,“body ...”表示内部定义上下文(guidereference),例如在 lambda 正文中,“form ...”表示所有非表达式上下文,如 begin 文档中。

于 2013-04-25T19:28:38.850 回答
-1

或者您可以将表达式包装在 (begin) eg(begin (define x 10) (define y 100) (define z 1000))

于 2015-11-11T05:09:48.810 回答