美文网首页
PLAI_Chapter7: Functions Anywher

PLAI_Chapter7: Functions Anywher

作者: thehgz | 来源:发表于2015-12-11 21:30 被阅读55次

    The introduction to the Scheme programming language definition establishes this design principle:


    Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary.


    以下是到37页为止的解释器,无闭包,会导致dynamic scoping。

    In other words, we’re again failing to faithfully capture what substitution would have done. A function value needs to remember the substitutions that have already been applied to it. Because we’re representing substitutions using an environment, a function value therefore needs to be bundled with an environment. This resulting data structure is called a closure.

    #lang plai-typed
    
    (define-type Value
      [numV (n : number)]
      [funV (name : symbol) (arg : symbol) (body : ExprC)])
    
    (define-type ExprC
      [numC (n : number)]
      [idC (s : symbol)]
      [appC (fun : ExprC) (arg : ExprC)]
      [plusC (l : ExprC) (r : ExprC)]
      [multC (l : ExprC) (r : ExprC)]
      [fdC (name : symbol) (arg : symbol) (body : ExprC)])
    
    (define (lookup [n : symbol] [env : Env]) : Value
      (cond
        [(empty? env) (error 'lookup "Symbol not found in env")]
        [(cons? env) (cond
                       [(equal? n (bind-name (first env))) (bind-val (first env))]
                       [else (lookup n (rest env))])]))
    
    (define-type Binding
      [bind (name : symbol) (val : Value)])
    (define-type-alias Env (listof Binding))
    (define mt-env empty)
    (define extend-env cons)
    
    (define (num+ [l : Value] [r : Value]) : Value
      (cond
        [(and (numV? l) (numV? r))
         (numV (+ (numV-n l) (numV-n r)))]
        [else
         (error 'num+ "one argument was not a number")]))
    
    (define (num* [l : Value] [r : Value]) : Value
      (cond
        [(and (numV? l) (numV? r))
         (numV (* (numV-n l) (numV-n r)))]
        [else
         (error 'num* "one argument was not a number")]))
    
    (define (interp [expr : ExprC] [env : Env]) : Value
      (type-case ExprC expr
        [numC (n) (numV n)]
        [idC (n) (lookup n env)]
        [plusC (l r) (num+ (interp l env) (interp r env))]
        [multC (l r) (num* (interp l env) (interp r env))]
        [fdC (n a b) (funV n a b)]
        [appC (f a) (local ([define fd (interp f env)])
                      (interp (funV-body fd)
                              (extend-env (bind (funV-arg fd)
                                                (interp a env))
                                          mt-env)))]))
    
    

    改为带closure的

    #lang plai-typed
    
    (define-type Value
      [numV (n : number)]
      [closV (arg : symbol) (body : ExprC) (env : Env)])
    
    (define-type ExprC
      [numC (n : number)]
      [idC (s : symbol)]
      [appC (fun : ExprC) (arg : ExprC)]
      [plusC (l : ExprC) (r : ExprC)]
      [multC (l : ExprC) (r : ExprC)]
      [lamC (arg : symbol) (body : ExprC)])
    
    (define (lookup [n : symbol] [env : Env]) : Value
      (cond
        [(empty? env) (error 'lookup "Symbol not found in env")]
        [(cons? env) (cond
                       [(equal? n (bind-name (first env))) (bind-val (first env))]
                       [else (lookup n (rest env))])]))
    
    (define-type Binding
      [bind (name : symbol) (val : Value)])
    (define-type-alias Env (listof Binding))
    (define mt-env empty)
    (define extend-env cons)
    
    (define (num+ [l : Value] [r : Value]) : Value
      (cond
        [(and (numV? l) (numV? r))
         (numV (+ (numV-n l) (numV-n r)))]
        [else
         (error 'num+ "one argument was not a number")]))
    
    (define (num* [l : Value] [r : Value]) : Value
      (cond
        [(and (numV? l) (numV? r))
         (numV (* (numV-n l) (numV-n r)))]
        [else
         (error 'num+ "one argument was not a number")]))
    
    (define (interp [expr : ExprC] [env : Env]) : Value
      (type-case ExprC expr
        [numC (n) (numV n)]
        [idC (n) (lookup n env)]
        [plusC (l r) (num+ (interp l env) (interp r env))]
        [multC (l r) (num* (interp l env) (interp r env))]
        [lamC (a b) (closV a b env)]
        [appC (f a) (local ([define f-value (interp f env)])
                      (interp (closV-body f-value)
                              (extend-env (bind (closV-arg f-value)
                                                (interp a env))
                                          (closV-env f-value))))]))
    
    

    Sugaring Over Anonymity

    left-left-lambda

    ((lambda (double)
        (double 10))
     (lambda (x) (+ x x)))
    ;=>
    (let ([double (lambda (x) (+ x x))])
        (double 10))
    

    7.4 Substitution, Again

    (lambda (f)
      (lambda (x)
     (f 10)))
    ;其中f是
      (lambda (y) (+ x y))
    

    直接替换会导致dynamic scoping.
    利用α-convention。

      (lambda (f1)
          (lambda (x1)
        (f1 10)))
    (lambda (y1) (+ x y1))
    
    (lambda (x1)
        ((lambda (y1) (+ x y1)) 10))
    ;x是未定义的自由变量,正是期待的行为
    

    相关文章

      网友评论

          本文标题:PLAI_Chapter7: Functions Anywher

          本文链接:https://www.haomeiwen.com/subject/pxedhttx.html