我正在学习Scheme(使用Racket),但我遇到的一个挑战是尝试执行以下代码,这意味着使用eval
从用户输入执行Racket代码:
(display (eval (read)))
这是迄今为止我观察到的一些奇怪的行为:
(display (eval (read)))
在运行定义时提示键盘输入,如预期的那样。但是,提供输入
((lambda (x) (+ x 1)) 1)
给出错误
?: function application is not allowed;
no #%app syntax transformer is bound in: ((lambda (x) (+ x 1)) 1)
另一方面,使用(display ((eval (read)) 1))
并提供输入
(lambda (x) (+ x 1))
返回错误
lambda: unbound identifier;
also, no #%app syntax transformer is bound in: lambda
(display (eval (read)))
并提供((lambda (x) (+ x 1)) 1)
,而不是定义窗格,会按预期打印出2
。这种行为的原因是什么?
答案 0 :(得分:8)
看起来您没有设置命名空间。如果您在文件中运行(eval (read))
,则它无法正常工作,因为默认情况下current-namespace
设置为空命名空间。您可以先设置racket/base
(current-namespace (make-base-namespace))
#lang racket
(current-namespace (make-base-namespace))
(println (eval (read)))
运行此程序并为其输入((lambda (x) (+ x 1)) 1)
会导致打印2
。
它在交互窗口(您的怪异行为列表的第3项)中工作的原因是,在交互窗口中,current-namespace
参数设置为文件的命名空间。
对于定义窗口(主程序),情况并非如此,因此您必须自己设置current-namespace
,或将名称空间作为第二个参数传递给eval
:
#lang racket
(define ns (make-base-namespace))
(println (eval (read) ns))
答案 1 :(得分:1)
Racket,该软件包,支持R5RS和R6RS,可能会获得对R7RS的支持。该软件在其自己的Racket语言系列中也有几种非标准语言,与Scheme有很多共同之处,但不是Scheme 。亚历克斯已经为这种语言做了很好的答案,所以我会添加有关Scheme的信息,因为你写的是学习Scheme,这与学习Racket不同,当涉及到eval
等一些极端案例时。
eval
是一个程序,它在不同的Scheme报告之间发生了重大变化,因为它在R5RS中成为强制性的。以下是该标准不同版本的一些示例:
#!r6rs
(import (rnrs)
(rnrs eval))
(display (eval '((lambda (x) (+ x 1)) 1)
(environment '(rnrs))))
; ==> undefined, prints 2
略长但仍然常用的R5RS:
#!r5rs
(display (eval '((lambda (x) (+ x 1)) 1)
(scheme-report-environment 5)))
; ==> undefined, prints 2
R7RS到目前为止只批准了它的小版本:
#!r7rs
(import (scheme)
(scheme eval))
(display (eval '((lambda (x) (+ x 1)) 1)
(environment '(scheme))))
; ==> undefined, prints 2