计划中的词汇范围

时间:2018-02-23 12:17:07

标签: scheme programming-languages lexical-scope

我试图理解词法和动态范围的概念以及它们之间的差异。 我们来看看下面的代码:

(let ((a 1)
      (b 2))
  (letrec ((f (lambda () F))
            (g (lambda (c) G)))
    (lambda (d)
      (+ (f) (g b)))))

对于表达式F和G,哪些变量位于(lambda(d)...)的词法范围内?

1 个答案:

答案 0 :(得分:1)

(lambda(d)...)d作为绑定变量,fg a b以及所有全局范围作为自由变量。

修改

只是为了演示Scheme中的代码以及其他相同绑定是动态的语言。由于您的两个函数都没有相互调用,因此您可以将它们保存在同一个let

(define test
  (let ((a 1)
        (b 2)
        (f (lambda () F))
        (g (lambda (c) G)))
    (lambda (d)
      (+ (f) (g b)))))

;; for the test we need the F and G defined
(define F 10)
(define G 20)

(test 4) ; ==> 30 (aka (+ F G))

lambda被评估时,即使在let消失之后,它从词法范围使用的变量依然存在。在一个动态范围内,这不是真的:

(test 4)
; ERROR f: unbound identifier

原因是在评估lamba时存在abfg,而没有像词法范围那样捕获变量,因此当程序test成立时,不再存在任何局部变量。事实上你不妨这样写:

;; in a dynamic lisp this s the same 
(define test
  (lambda (d)
    (+ (f) (g b))))

当你调用函数(也就是动态的)

时,你必须确保变量存在
(define g (lambda (v) 1337))
(define f (lambda () 3.1415927))
(define b 13)
(test 4) ; ==> 1340.1415927

现在,如果要在全局范围中添加上述定义并保留原始定义,则仍然会得到30,因为词法lisp使用更接近的词法绑定而不是全局绑定。

另一个很好的例子是:

(define x 10)
(define (test v)
  (+ x v))

(let ((x 20))
  (test 10))
; ==> ?

在词汇lisp中,结果总是20,因为testlet一无所知,因为它不在词法范围内。 x始终是全局绑定x。在dymamic lisp中,x中的let是距运行时最接近的30,因为x中的testxletx相同,它会影响全局XmlDocument xdoc = new XmlDocument(); // Get Request Xml for each of the case xdoc.LoadXml(xmlContent); XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable); nsmgr.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/"); nsmgr.AddNamespace("sc", "http://tempuri.org/");