无法在Racket中的用户输入上使用eval

时间:2016-05-16 02:50:37

标签: scheme lisp racket

我正在学习Scheme(使用Racket),但我遇到的一个挑战是尝试执行以下代码,这意味着使用eval从用户输入执行Racket代码:

(display (eval (read)))

这是迄今为止我观察到的一些奇怪的行为:

    定义窗口中的
  1. (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)

  2. 另一方面,使用(display ((eval (read)) 1))并提供输入
    (lambda (x) (+ x 1))

    返回错误
    lambda: unbound identifier; also, no #%app syntax transformer is bound in: lambda

  3. 但是,在控制台窗格中运行(display (eval (read)))并提供((lambda (x) (+ x 1)) 1),而不是定义窗格,会按预期打印出2
  4. 这种行为的原因是什么?

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