我正在学习“编程语言:应用程序和解释”,执行后可以在 DrRacket 5.2.1 中运行前两章的示例#lang plai
。但是当我输入第 3 章的第一个示例时,如下所示:
(with (x 5) (+ x x))
我收到以下错误:
reference to an identifier before its definition: with
with
我在这本书中没有找到 的定义。我需要图书馆吗?
构造with
不是您在自己的程序中使用的东西——它是存在于您定义的语言中的东西。换句话说,它是你实现的东西,而不是你使用的东西。请注意,书籍总是将它与花括号一起使用,{with {x ...} ...}
这是为了避免您遇到的这种确切的混淆——花括号始终用于您实现的语言的代码中,圆括号用于您自己的实现的代码。
请注意,在 Racket 中定义自己的with
内容很简单,但这是错误的,并且可能会让您更加困惑。与其尝试在 Racket 中使用它,不如按照本书进行操作,在第 3 章结束时,您将拥有一个适用于 WAE 语言的解释器——然后您将能够使用它来运行 WAE 程序使用with
.
附带说明一下,如果您正在寻找与 类似的 Racket 表单,with
请查看let
- 唯一的区别是它let
允许您指定多个绑定,而不仅仅是一个。
(with (x a) <body>) is just a synonym for ((lambda x <body>) a)
如果您仍然有问题,您可以使用
((lambda x (+ x x)) 5)
很抱歉我昨天无法测试这些示例!好像还是有错误,我把第3章末尾的这些代码打了如下:
(define (parse sexp)
(cond
[(number? sexp) (num sexp)]
[(list? sexp)
(case (first sexp)
[(+) (add (parse (second sexp))
(parse (third sexp)))]
[(-) (sub (parse (second sexp))
(parse (third sexp)))])]))
(define-type WAE
[num (n number?)]
[add (lhs WAE?)(rhs WAE?)]
[sub (lhs WAE?) (rhs WAE?)]
[with (name symbol?) (named-expr WAE?)(body WAE?)]
[id (name symbol?)])
(define (subst expr sub-id val)
(type-case WAE expr
[num (n) expr]
[add (l r) (add (subst l sub-id val)
(subst r sub-id val))]
[sub (l r) (sub (subst l sub-id val)
(subst r sub-id val))]
[with (bound-id named-expr bound-body)
(if (symbol=? bound-id sub-id)
(with bound-id
(subst named-expr sub-id val)
bound-body)
(with bound-id
(subst named-expr sub-id val)
(subst bound-body sub-id val)))]
[id (v) (if (symbol=? v sub-id) val expr)]))
(define (calc expr)
(type-case WAE expr
[num (n) n]
[add (l r) (+ (calc l) (calc r))]
[sub (l r) (- (calc l) (calc r))]
[with (bound-id named-expr bound-body)
(calc (subst bound-body
bound-id
(num (calc named-expr))))]
[id (v) (error 'calc "free identifier")]))
然后,我在第 21 页测试“with”,如下所示
(calc (parse '{with {x {+ 5 5}} {+ xx}}))
我得到了错误:
"type-case: expected a value from type WAE, got: #"
原因是需要更新解析,我从谷歌获得了一些关于第 3 章的片段,例如,在CS 345 Progamming Languages中,它的解析定义如下:
(define parse
(lambda (sexp)
(cond
[(number? sexp) (num sexp)]
[(symbol? sexp) (id sexp)]
[(list? sexp)
(case (first sexp)
[(+)(add (parse (second sexp))
(parse (third sexp)))]
[(-) (sub (parse (second sexp))
(parse (third sexp)))]
[(with) (with (first (second sexp))
(parse (second (second sexp)))
(parse (third sexp)))]
)])))
最后,我得到了正确的结果:
(calc (parse '{with {x {+ 5 5}} {+ xx}}) ) => 20