我正在学习"编程语言:应用和解释",在执行#lang plai
后,我可以在DrRacket 5.2.1中运行前两章的示例。但是当我输入第三章的第一个例子如下:
(with (x 5) (+ x x))
我得到以下错误:
reference to an identifier before its definition: with
我在这本书中没有找到with
的定义。我需要图书馆吗?
with
结构不是您在自己的程序中使用的东西,而是您定义的语言中存在的东西。换句话说,这是您实现的东西,而不是您使用的东西。请注意,这些书总是将其与大括号{with {x ...} ...}
一起使用,这是为了避免您所遇到的这种完全混乱——大括号总是用于您实现的语言中的代码,圆括号用于您自己实现的代码。
请注意,在Racket中定义自己的with
很简单,但这是错误的,可能会让您更加困惑。与其尝试在Racket中使用它,您只需按照本书进行操作,在第3章的末尾,您将有一个WAE语言的工作解释器,然后您就可以使用它来运行使用with
的WAE程序。
附带说明一下,如果您正在寻找类似于with
的Racket表单,那么请查看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"
(计算(解析"{与{x{+5 5}}{+x x}}}")
我得到了错误:
"type-case: expected a value from type WAE, got: #"
原因是需要更新解析,我从谷歌上得到了一些关于第3章的片段,例如,在CS 345编程语言中,它的解析定义如下:
(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(解析‘{with{x{+5 5}}}}{+x x}’)=>20