将sqrt函数添加到球拍pl 03的语言中

时间:2016-06-04 10:07:04

标签: racket typed-racket

我的任务是在我的球拍语言中添加名为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 ...)

我想念并需要做些什么改变?

1 个答案:

答案 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会消耗一个数字...