help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: DynamicBindingVsLexicalBinding


From: Drew Adams
Subject: RE: DynamicBindingVsLexicalBinding
Date: Sat, 12 Oct 2013 13:53:43 -0700 (PDT)

> Consider this rather obvious higher-order function:
> (defun addinator (a) (lambda (b) (+ a b)))
> 
> ;; This doesn't work with dynamic binding, at all
> (funcall (addinator 3) 4)
> 
> ;; This returns wrong result with dynamic binding
> (let ((a 42)) (funcall (addinator 3) 4))

Actually, both examples "work" with dynamic binding.  They do
exactly the code says they do.  They simply work according to
dynamic binding rules, not lexical binding rules.

What is wrong is to expect lexical binding behavior without
lexical binding!

Both correctly raise an error if `a' has no value.  `a' is a
free variable in your examples, when using dynamic binding.
and both work correctly, per dynamic binding behavior, if you
first give `a' a value, e.g., (setq a 9).

They just do not do what they would do with lexical binding;
that's all.

(setq a 9) ; Current dynamic value of `a' is 9.

(defun addinator (a) (lambda (b) (+ a b)))
  ; That's (lambda (b) (+ a b)), a program that looks up
  ; `a' in the current dynamic environment, adds it to
  ; passed argument `b', and returns the result.

(funcall (addinator 3) 4)
  ; That calls the result of (addinator 3) with argument 4.
  ; Which means it calls (lambda (b) (+ a b)) with arg 4.
  ; Which looks up the current dynamic binding of `a', which
  ; is 9, adds it to 4, and returns the result correctly: 13.

(let ((a 42)) (funcall (addinator 3) 4))
  ; That binds `a' to 42, changing the current dynamic binding
  ; of `a' to 42.  Then it calls (addinator 3) with arg 4.
  ; Which adds the current dynamic binding of `a', which is 42,
  ; to `b'.  The result is correct: 46.

`addinator' has this definition:
(lambda (a) (function (lambda (b) (+ a b))))

This is *not* a closure in Emacs Lisp.  It is a function whose
body is a *quoted* lambda expression that has a free variable,
`a'.  That free variable is looked up when that body function
is applied, not when `addinator' is defined.

The only thing wrong here is your mistaken expectation (and
the attendant naming of function `addinator').

IOW, the error is in looking for noon at 2:00: "chercher midi à quatorze 
heures".

Yes, it can be confusing.  No, dynamic binding is not very close
to functional programming or lambda calculus.  But it is not
wrong.  It just plays by different rules.

Using Emacs Lisp, like using Common Lisp, requires understanding
both kinds of behavior.

Yes, one can choose not to use any dynamically scoped variables.
Or one can choose not to use any lexically scoped variables.
Such a choice can simplify what one needs to understand.

"[I]t eliminates the problem of which variables lambda-expressions
use (when they attempt to use variables from their surrounding
context)."

That elimination happens with either simplification: stick to
dynamic-only or stick to lexical-only.  The difference between
the two eliminations is that with lexical scope you need only
look at the immediate code; whereas with dynamic scope you need
to think about time/state to understand the behavior.

And yes, it is generally easier to determine lexical scope
than dynamic scope: lexical means WYSIWYG.

But the language provides both, and learning the language means understanding 
both and how they can be used together.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]