我的任务是在我的球拍语言中添加名为sqrt +的新功能。
sqrt +函数返回列表,其中包含数字的根和他的负根。
通过Sqrt语法调用sqrt +函数的方法:
#lang pl 03
#| BNF for the MUWAE language:
<MUWAE> ::= <num>
| { + <MUWAE> <MUWAE> }
| { - <MUWAE> <MUWAE> }
| { * <MUWAE> <MUWAE> }
| { / <MUWAE> <MUWAE> }
| { Sqrt <MUWAE> }
| { with { <id> <WAE> } <MUWAE> }
| <id>
|#
;; MUWAE abstract syntax trees
(define-type MUWAE
[Num Number]
[Add MUWAE MUWAE]
[Sub MUWAE MUWAE]
[Mul MUWAE MUWAE]
[Div MUWAE MUWAE]
[Sqrt MUWAEE]
[Id Symbol]
[With Symbol MUWAE MUWAE])
(: parse-sexpr : Sexpr -> MUWAE)
;; to convert s-expressions into MUWAEs
(define (parse-sexpr sexpr)
(match sexpr
[(number: n) (Num n)]
[(symbol: name) (Id name)]
[(cons 'with more)
(match sexpr
[(list 'with (list (symbol: name) named) body)
(With name (parse-sexpr named) (parse-sexpr body))]
[else (error 'parse-sexpr "bad `with' syntax in ~s" sexpr)])]
[(list '+ lhs rhs) (Add (parse-sexpr lhs) (parse-sexpr rhs))]
[(list '- lhs rhs) (Sub (parse-sexpr lhs) (parse-sexpr rhs))]
[(list '* lhs rhs) (Mul (parse-sexpr lhs) (parse-sexpr rhs))]
[(list '/ lhs rhs) (Div (parse-sexpr lhs) (parse-sexpr rhs))]
[(list 'Sqrt s) (sqrt+ (parse-sexpr s))]
[else (error 'parse-sexpr "bad syntax in ~s" sexpr)]))
(: parse : String -> MUWAE)
;; parses a string containing a MUWAE expression to a MUWAE AST
(define (parse str)
(parse-sexpr (string->sexpr str)))
#| Formal specs for `subst':
(`N' is a <num>, `E1', `E2' are <MUWAE>s, `x' is some <id>,
`y' is a *different* <id>)
N[v/x] = N
{+ E1 E2}[v/x] = {+ E1[v/x] E2[v/x]}
{- E1 E2}[v/x] = {- E1[v/x] E2[v/x]}
{* E1 E2}[v/x] = {* E1[v/x] E2[v/x]}
{/ E1 E2}[v/x] = {/ E1[v/x] E2[v/x]}
y[v/x] = y
x[v/x] = v
{with {y E1} E2}[v/x] = {with {y E1[v/x]} E2[v/x]}
{with {x E1} E2}[v/x] = {with {x E1[v/x]} E2}
|#
(: subst : MUWAE Symbol MUWAE -> MUWAE)
;; substitutes the second argument with the third argument in the
;; first argument, as per the rules of substitution; the resulting
;; expression contains no free instances of the second argument
(define (subst expr from to)
(cases expr
[(Num n) expr]
[(Add l r) (Add (subst l from to) (subst r from to))]
[(Sub l r) (Sub (subst l from to) (subst r from to))]
[(Mul l r) (Mul (subst l from to) (subst r from to))]
[(Div l r) (Div (subst l from to) (subst r from to))]
[(Sqrt s) (sqrt+ (subst s from to))]
[(Id name) (if (eq? name from) to expr)]
[(With bound-id named-expr bound-body)
(With bound-id
(subst named-expr from to)
(if (eq? bound-id from)
bound-body
(subst bound-body from to)))]))
#| Formal specs for `eval':
eval(N) = N
eval({+ E1 E2}) = eval(E1) + eval(E2)
eval({- E1 E2}) = eval(E1) - eval(E2)
eval({* E1 E2}) = eval(E1) * eval(E2)
eval({/ E1 E2}) = eval(E1) / eval(E2)
eval(id) = error!
eval({with {x E1} E2}) = eval(E2[eval(E1)/x])
|#
(: eval : MUWAE -> Number)
;; evaluates MUWAE expressions by reducing them to numbers
(define (eval expr)
(cases expr
[(Num n) n]
[(Add l r) (+ (eval l) (eval r))]
[(Sub l r) (- (eval l) (eval r))]
[(Mul l r) (* (eval l) (eval r))]
[(Div l r) (/ (eval l) (eval r))]
[(Sqrt s) (sqrt+ (eval s))]
[(With bound-id named-expr bound-body)
(eval (subst bound-body
bound-id
(Num (eval named-expr))))]
[(Id name) (error 'eval "free identifier: ~s" name)]))
(: run : String -> Number)
;; evaluate a MUWAE program contained in a string
(define (run str)
(eval (parse str)))
(: sqrt+ : (Listof Number) -> (Listof Number))
;; a version of `sqrt' that takes a list of numbers, and return a list
;; with twice the elements, holding the two roots of each of the inputs;
;; throws an error if any input is negative.
(define (sqrt+ ns)
(cond [(null? ns) 0]
[(< (first ns) 0) (error 'ns "`sqrt' requires a nonnegative input ~s")]
[else (sqrt ns (* (sqrt ns) -1))]))
但是当我尝试运行我得到的语言时:
案例:以下变体缺少案例:(Sqrt ...)
我想念并需要做些什么改变?
答案 0 :(得分:1)
不试用你的程序:
[(Sqrt s) (sqrt+ (subst s from to))]
subst
函数中的似乎不正确。 subst
应该返回MUWAE
。但是,返回类型sqrt+
是一个数字列表。
另外,
[(Sqrt s) (sqrt+ (eval s))]
eval
函数中的似乎不正确,因为eval
应该返回一个数字。但是,返回类型sqrt+
是一个数字列表。同样,(eval s)
的类型应该是一个数字,但sqrt+
会使用一个数字列表。
最后,我还认为您sqrt+
的实施也是错误的。特别是,写[else (sqrt ns (* (sqrt ns) -1))]
是没有意义的,因为sqrt
会消耗一个数字...