unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
From: Drew Adams <drew.adams@oracle.com>
To: "Dmitry Gutov" <dgutov@yandex.ru>,
	"Andreas Röhler" <andreas.roehler@easy-emacs.de>
Cc: "help-gnu-emacs@gnu.org List" <help-gnu-emacs@gnu.org>
Subject: RE: DynamicBindingVsLexicalBinding
Date: Sat, 12 Oct 2013 13:53:43 -0700 (PDT)	[thread overview]
Message-ID: <3da7567e-5a00-400a-bf72-5430740e2782@default> (raw)
In-Reply-To: <871u3qjq0j.fsf@yandex.ru>

> 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	other threads:[~2013-10-12 20:53 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-12 17:56 DynamicBindingVsLexicalBinding Andreas Röhler
2013-10-12 18:35 ` DynamicBindingVsLexicalBinding Dmitry Gutov
2013-10-12 20:53   ` Drew Adams [this message]
2013-10-13  5:09     ` DynamicBindingVsLexicalBinding Thien-Thi Nguyen
2013-10-13  7:54   ` DynamicBindingVsLexicalBinding Andreas Röhler
2013-10-13 13:46     ` DynamicBindingVsLexicalBinding Kai Großjohann
2013-10-13 16:21       ` DynamicBindingVsLexicalBinding Drew Adams
2013-10-14 11:21         ` DynamicBindingVsLexicalBinding Phillip Lord
2013-10-14 13:45           ` DynamicBindingVsLexicalBinding Drew Adams
2013-10-14 16:05             ` DynamicBindingVsLexicalBinding Phillip Lord
2013-10-14 21:32           ` DynamicBindingVsLexicalBinding Kai Großjohann
2013-10-15 11:27             ` DynamicBindingVsLexicalBinding Phillip Lord
2013-10-15 20:43               ` DynamicBindingVsLexicalBinding Kai Großjohann
2013-10-16 12:57                 ` DynamicBindingVsLexicalBinding Phillip Lord
     [not found]                 ` <mailman.4127.1381928277.10748.help-gnu-emacs@gnu.org>
2013-10-16 14:26                   ` DynamicBindingVsLexicalBinding Barry Margolin
     [not found]       ` <mailman.3929.1381681317.10748.help-gnu-emacs@gnu.org>
2013-10-14 11:27         ` DynamicBindingVsLexicalBinding Rustom Mody
2013-10-14 11:15 ` DynamicBindingVsLexicalBinding Phillip Lord
     [not found] <mailman.3891.1381600459.10748.help-gnu-emacs@gnu.org>
2013-10-13  3:34 ` DynamicBindingVsLexicalBinding Barry Margolin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3da7567e-5a00-400a-bf72-5430740e2782@default \
    --to=drew.adams@oracle.com \
    --cc=andreas.roehler@easy-emacs.de \
    --cc=dgutov@yandex.ru \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).