美文网首页Lisp
[Emacs Lisp] 启用变量的词法作用域

[Emacs Lisp] 启用变量的词法作用域

作者: 何幻 | 来源:发表于2017-05-10 14:11 被阅读114次

    1. setq lexical-binding失效

    从Emacs 24开始,Emacs可以启用变量的lexical binding模式,
    Emacs Lisp Reference:11.9.4 Using Lexical Binding中提到,

    When loading an Emacs Lisp file or evaluating a Lisp buffer, lexical binding is enabled if the buffer-local variable lexical-binding is non-nil:

    —— Variable: lexical-binding
    If this buffer-local variable is non-nil, Emacs Lisp files and buffers are evaluated using lexical binding instead of dynamic binding. (However, special variables are still dynamically bound; see below.) If nil, dynamic binding is used for all local variables. This variable is typically set for a whole Emacs Lisp file, as a file local variable.

    Note that unlike other such variables, this one must be set in the first line of a file.

    然而,以下代码,M-x eval-buffer之后,仍然会报错,
    仍然使用了变量的dynamic binding模式,

    (setq lexical-binding t)
    
    (setq test (let ((foo "bar"))
             (lambda () 
               foo)))
    
    (let ((foo "something-else"))
      (funcall test))    ; "something-else"
    
    (funcall test)    ; Error! Symbol’s value as variable is void: foo
    

    注:
    (1)依次对每个表达式使用:M-x eval-last-sexp(快捷键:C-x C-e),
    是不会报错的,确实启用了词法作用域。
    但是使用M-x eval-buffer求值整个buffer,或者在其他文件中load本文件时,就会报错。
    (2)M-x eval-buffer,可以简写为M-x ev-b

    2. 解决方案

    将文件的第一行改成:; -*- lexical-binding: t -*-
    Emacs Version: 25.2

    例如:M-x eval-bufferload都不报错,启用了词法作用域。

    ; -*- lexical-binding: t -*-
    
    (setq test (let ((foo "bar"))
             (lambda () 
               foo)))
    
    (let ((foo "something-else"))
      (funcall test))    ; "bar"
    
    (funcall test)    ; "bar"
    

    注:
    (1); -*- lexical-binding: t -*-必须位于文件或者buffer的第一行。
    (2)这条指令是以注释的方式存在的,在-*- ... -*-外面可以写任何其他注释,此外多个“;”肯定也是可以的“;;”,例如:;; 123 -*- lexical-binding: t -*- 456

    3. File Variables

    -*- mode: modename; var: value; ... -*-
    类似这样的写法,实际上是在Emacs中指定了File Variables。

    GNU Emacs manual: 51.2.4.1 Specifying File Variables中指出,

    There are two ways to specify file local variable values: in the first line, or with a local variables list.

    Here's how to specify them in the first line:

    -*- mode: modename; var: value; ... -*-
    

    A local variables list starts with a line containing the string ‘Local Variables:’, and ends with a line containing the string ‘End:’. In between come the variable names and values, one set per line, like this:

    /* Local Variables:  */
    /* mode: c           */
    /* comment-column: 0 */
    /* End:              */
    

    参考

    GNU Emacs manual
    GNU Emacs Lisp Reference Manual
    Emacs Wiki: Lexical binding

    相关文章

      网友评论

        本文标题:[Emacs Lisp] 启用变量的词法作用域

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