emacs-diffs
[Top][All Lists]
Advanced

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

master 7e4a4b762e7 2/4: Describe lexical binding before dynamic


From: Mattias Engdegård
Subject: master 7e4a4b762e7 2/4: Describe lexical binding before dynamic
Date: Mon, 23 Oct 2023 08:50:26 -0400 (EDT)

branch: master
commit 7e4a4b762e73ec03be18a149b737447facff3612
Author: Mattias Engdegård <mattiase@acm.org>
Commit: Mattias Engdegård <mattiase@acm.org>

    Describe lexical binding before dynamic
    
    * doc/lispref/variables.texi (Variable Scoping)
    (Lexical Binding, Dynamic Binding):
    Alter the presentation order from the point of view that lexical
    binding is the standard discipline (if not always the default) and
    dynamic binding an alternative, which corresponds better to Elisp
    today.  Modernise parts of the text.
    * doc/lispref/elisp.texi (Top): Update menu.
---
 doc/lispref/elisp.texi     |   4 +-
 doc/lispref/variables.texi | 254 ++++++++++++++++++++++-----------------------
 2 files changed, 127 insertions(+), 131 deletions(-)

diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index 72441c8d442..8bf8358153c 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -534,9 +534,9 @@ Variables
 
 Scoping Rules for Variable Bindings
 
-* Dynamic Binding::         The default for binding local variables in Emacs.
+* Lexical Binding::         The standard type of local variable binding.
+* Dynamic Binding::         A different type of local variable binding.
 * Dynamic Binding Tips::    Avoiding problems with dynamic binding.
-* Lexical Binding::         A different type of local variable binding.
 * Using Lexical Binding::   How to enable lexical binding.
 * Converting to Lexical Binding:: Convert existing code to lexical binding.
 
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 779f6233735..f793a83a703 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -976,50 +976,152 @@ Variables}).  This section describes exactly what this 
means.
 binding can be accessed.  @dfn{Extent} refers to @emph{when}, as the
 program is executing, the binding exists.
 
-@cindex dynamic binding
-@cindex dynamic scope
-@cindex dynamic extent
-  By default, the local bindings that Emacs creates are @dfn{dynamic
-bindings}.  Such a binding has @dfn{dynamic scope}, meaning that any
-part of the program can potentially access the variable binding.  It
-also has @dfn{dynamic extent}, meaning that the binding lasts only
-while the binding construct (such as the body of a @code{let} form) is
-being executed.
-
 @cindex lexical binding
 @cindex lexical scope
 @cindex indefinite extent
-  Emacs can optionally create @dfn{lexical bindings}.  A lexical
-binding has @dfn{lexical scope}, meaning that any reference to the
-variable must be located textually within the binding
+  For historical reasons, there are two dialects of Emacs Lisp,
+selected via the @code{lexical-binding} buffer-local variable.
+In the modern Emacs Lisp dialect, local bindings are lexical by default.
+A @dfn{lexical binding} has @dfn{lexical scope}, meaning that any
+reference to the variable must be located textually within the binding
 construct@footnote{With some exceptions; for instance, a lexical
 binding can also be accessed from the Lisp debugger.}.  It also has
 @dfn{indefinite extent}, meaning that under some circumstances the
 binding can live on even after the binding construct has finished
-executing, by means of special objects called @dfn{closures}.
+executing, by means of objects called @dfn{closures}.
 
-  The dynamic binding was (and still is) the default in Emacs for many
-years, but lately Emacs is moving towards using lexical binding in
-more and more places, with the goal of eventually making that the
-default.
+@cindex dynamic binding
+@cindex dynamic scope
+@cindex dynamic extent
+  Local bindings can also be dynamic, which they always are in the
+old Emacs Lisp dialect and optionally in the modern dialect.
+A @dfn{dynamic binding} has @dfn{dynamic scope}, meaning that any
+part of the program can potentially access the variable binding.  It
+also has @dfn{dynamic extent}, meaning that the binding lasts only
+while the binding construct (such as the body of a @code{let} form) is
+being executed.
 
-  The following subsections describe dynamic binding and lexical
+  The old dynamic-only Emacs Lisp dialect is still the default in code
+loaded or evaluated from Lisp files that lack a dialect declaration.
+Eventually the modern dialect will be made the default.
+All Lisp files should declare the dialect used to ensure that they
+keep working correctly in the future.
+
+  The following subsections describe lexical binding and dynamic
 binding in greater detail, and how to enable lexical binding in Emacs
 Lisp programs.
 
 @menu
-* Dynamic Binding::         The default for binding local variables in Emacs.
+* Lexical Binding::         The standard type of local variable binding.
+* Dynamic Binding::         A different type of local variable binding.
 * Dynamic Binding Tips::    Avoiding problems with dynamic binding.
-* Lexical Binding::         A different type of local variable binding.
 * Using Lexical Binding::   How to enable lexical binding.
 * Converting to Lexical Binding:: Convert existing code to lexical binding.
 @end menu
 
+@node Lexical Binding
+@subsection Lexical Binding
+
+Lexical binding is only available in the modern Emacs Lisp dialect.
+(@xref{Using Lexical Binding}.)
+A lexically-bound variable has @dfn{lexical scope}, meaning that any
+reference to the variable must be located textually within the binding
+construct.  Here is an example
+
+@example
+@group
+(let ((x 1))    ; @r{@code{x} is lexically bound.}
+  (+ x 3))
+     @result{} 4
+
+(defun getx ()
+  x)            ; @r{@code{x} is used free in this function.}
+
+(let ((x 1))    ; @r{@code{x} is lexically bound.}
+  (getx))
+@error{} Symbol's value as variable is void: x
+@end group
+@end example
+
+@noindent
+Here, the variable @code{x} has no global value.  When it is lexically
+bound within a @code{let} form, it can be used in the textual confines
+of that @code{let} form.  But it can @emph{not} be used from within a
+@code{getx} function called from the @code{let} form, since the
+function definition of @code{getx} occurs outside the @code{let} form
+itself.
+
+@cindex lexical environment
+  Here is how lexical binding works.  Each binding construct defines a
+@dfn{lexical environment}, specifying the variables that are bound
+within the construct and their local values.  When the Lisp evaluator
+wants the current value of a variable, it looks first in the lexical
+environment; if the variable is not specified in there, it looks in
+the symbol's value cell, where the dynamic value is stored.
+
+@cindex closures, example of using
+  Lexical bindings have indefinite extent.  Even after a binding
+construct has finished executing, its lexical environment can be
+``kept around'' in Lisp objects called @dfn{closures}.  A closure is
+created when you define a named or anonymous function with lexical
+binding enabled.  @xref{Closures}, for details.
+
+  When a closure is called as a function, any lexical variable
+references within its definition use the retained lexical environment.
+Here is an example:
+
+@example
+(defvar my-ticker nil)   ; @r{We will use this dynamically bound}
+                         ; @r{variable to store a closure.}
+
+(let ((x 0))             ; @r{@code{x} is lexically bound.}
+  (setq my-ticker (lambda ()
+                    (setq x (1+ x)))))
+    @result{} (closure ((x . 0)) ()
+          (setq x (1+ x)))
+
+(funcall my-ticker)
+    @result{} 1
+
+(funcall my-ticker)
+    @result{} 2
+
+(funcall my-ticker)
+    @result{} 3
+
+x                        ; @r{Note that @code{x} has no global value.}
+@error{} Symbol's value as variable is void: x
+@end example
+
+@noindent
+The @code{let} binding defines a lexical environment in which the
+variable @code{x} is locally bound to 0.  Within this binding
+construct, we define a lambda expression which increments @code{x} by
+one and returns the incremented value.  This lambda expression is
+automatically turned into a closure, in which the lexical environment
+lives on even after the @code{let} binding construct has exited.  Each
+time we evaluate the closure, it increments @code{x}, using the
+binding of @code{x} in that lexical environment.
+
+  Note that unlike dynamic variables which are tied to the symbol
+object itself, the relationship between lexical variables and symbols
+is only present in the interpreter (or compiler).  Therefore,
+functions which take a symbol argument (like @code{symbol-value},
+@code{boundp}, and @code{set}) can only retrieve or modify a
+variable's dynamic binding (i.e., the contents of its symbol's value
+cell).
+
 @node Dynamic Binding
 @subsection Dynamic Binding
 
-  By default, the local variable bindings made by Emacs are dynamic
-bindings.  When a variable is dynamically bound, its current binding
+  Local variable bindings are dynamic in the modern Lisp dialect for
+special variables, and for all variables in the old Lisp
+dialect.  (@xref{Using Lexical Binding}.)
+Dynamic variable bindings have their uses but are in general more
+error-prone and less efficient than lexical bindings, and the compiler
+is less able to find mistakes in code using dynamic bindings.
+
+  When a variable is dynamically bound, its current binding
 at any point in the execution of the Lisp program is simply the most
 recently-created dynamic local binding for that symbol, or the global
 binding if there is no such local binding.
@@ -1086,9 +1188,6 @@ a dynamic local binding, Emacs records the contents of 
the value cell
 value cell.  When the binding construct finishes executing, Emacs pops
 the old value off the stack, and puts it in the value cell.
 
-  Note that when code using Dynamic Binding is native compiled the
-native compiler will not perform any Lisp specific optimization.
-
 @node Dynamic Binding Tips
 @subsection Proper Use of Dynamic Binding
 
@@ -1135,109 +1234,6 @@ variables like @code{case-fold-search}:
 @end example
 @end itemize
 
-@node Lexical Binding
-@subsection Lexical Binding
-
-  Lexical binding was introduced to Emacs, as an optional feature, in
-version 24.1.  We expect its importance to increase with time.
-Lexical binding opens up many more opportunities for optimization, so
-programs using it are likely to run faster in future Emacs versions.
-Lexical binding is also more compatible with concurrency, which was
-added to Emacs in version 26.1.
-
-  A lexically-bound variable has @dfn{lexical scope}, meaning that any
-reference to the variable must be located textually within the binding
-construct.  Here is an example
-@iftex
-(see the next subsection, for how to actually enable lexical binding):
-@end iftex
-@ifnottex
-(@pxref{Using Lexical Binding}, for how to actually enable lexical binding):
-@end ifnottex
-
-@example
-@group
-(let ((x 1))    ; @r{@code{x} is lexically bound.}
-  (+ x 3))
-     @result{} 4
-
-(defun getx ()
-  x)            ; @r{@code{x} is used free in this function.}
-
-(let ((x 1))    ; @r{@code{x} is lexically bound.}
-  (getx))
-@error{} Symbol's value as variable is void: x
-@end group
-@end example
-
-@noindent
-Here, the variable @code{x} has no global value.  When it is lexically
-bound within a @code{let} form, it can be used in the textual confines
-of that @code{let} form.  But it can @emph{not} be used from within a
-@code{getx} function called from the @code{let} form, since the
-function definition of @code{getx} occurs outside the @code{let} form
-itself.
-
-@cindex lexical environment
-  Here is how lexical binding works.  Each binding construct defines a
-@dfn{lexical environment}, specifying the variables that are bound
-within the construct and their local values.  When the Lisp evaluator
-wants the current value of a variable, it looks first in the lexical
-environment; if the variable is not specified in there, it looks in
-the symbol's value cell, where the dynamic value is stored.
-
-@cindex closures, example of using
-  Lexical bindings have indefinite extent.  Even after a binding
-construct has finished executing, its lexical environment can be
-``kept around'' in Lisp objects called @dfn{closures}.  A closure is
-created when you define a named or anonymous function with lexical
-binding enabled.  @xref{Closures}, for details.
-
-  When a closure is called as a function, any lexical variable
-references within its definition use the retained lexical environment.
-Here is an example:
-
-@example
-(defvar my-ticker nil)   ; @r{We will use this dynamically bound}
-                         ; @r{variable to store a closure.}
-
-(let ((x 0))             ; @r{@code{x} is lexically bound.}
-  (setq my-ticker (lambda ()
-                    (setq x (1+ x)))))
-    @result{} (closure ((x . 0)) ()
-          (setq x (1+ x)))
-
-(funcall my-ticker)
-    @result{} 1
-
-(funcall my-ticker)
-    @result{} 2
-
-(funcall my-ticker)
-    @result{} 3
-
-x                        ; @r{Note that @code{x} has no global value.}
-@error{} Symbol's value as variable is void: x
-@end example
-
-@noindent
-The @code{let} binding defines a lexical environment in which the
-variable @code{x} is locally bound to 0.  Within this binding
-construct, we define a lambda expression which increments @code{x} by
-one and returns the incremented value.  This lambda expression is
-automatically turned into a closure, in which the lexical environment
-lives on even after the @code{let} binding construct has exited.  Each
-time we evaluate the closure, it increments @code{x}, using the
-binding of @code{x} in that lexical environment.
-
-  Note that unlike dynamic variables which are tied to the symbol
-object itself, the relationship between lexical variables and symbols
-is only present in the interpreter (or compiler).  Therefore,
-functions which take a symbol argument (like @code{symbol-value},
-@code{boundp}, and @code{set}) can only retrieve or modify a
-variable's dynamic binding (i.e., the contents of its symbol's value
-cell).
-
 @node Using Lexical Binding
 @subsection Using Lexical Binding
 



reply via email to

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