elisp 中的 lambda 函数作用域
lambda function scope in elisp
我在设计程序时犯了一个错误。
我需要按值对散列 table 中的部分条目进行排序。
我会用演示代码来讲述这个故事。
;; A loacal hash table......
(let ((table (make-hash-table))
(list-of-interest nil))
(puthash 0 "Foo" table)
(puthash 1 "Bar" table)
;;..........
(puthash 9999 "Bra" table)
;; And I have a list with key I am interested to sort
(dotimes (var 50)
(add-to-list list-of-interest (random 9999)))
;; Sorting should depends on comparing the associated string
;; For exmple,
;; If the list is (0 1 9999)
;; I hope to get (1 9999 0) as "Bar" < "Bra" < "Foo"
;; However, I forgot that the table is a local variable
;; I can't pass the table to the predicate function by any means
;; So the predicate function can never resolve the string from the key
(sort list-of-interest 'predicate)
;; When I was thinking to rewrite the code
;; I find that a lambda function can 'grab' the local variable
(sort list-of-interest (lambda (a b)
(string-lessp (gethash a table) (gethash b table))))
;; return value
table)
我在心里提出了两个问题:
- 最重要的问题:lambda函数可以吗?
- 我相信 lambda 是一个像其他函数一样没有名字的函数。为什么它可以'grab'局部变量?
是的,你的 lambda 函数没问题。
Emacs Lisp 有两种类型的绑定:动态绑定和词法绑定。动态绑定是默认设置,您可以通过将此行添加为 Emacs Lisp 源文件的第一行来在每个文件的基础上激活词法绑定:
;;; -*- lexical-binding: t; -*-
(这会将本地缓冲区中的变量 lexical-binding
设置为 t
。)
您的 lambda 函数可以正确处理动态绑定和词法绑定。
它与动态绑定一起工作正常,因为该函数仅在 sort
函数运行时被调用,并且在其执行期间有一个名为 table
的 let-bound 变量,其中包含所需的值.
它与词法绑定一起工作正常,因为该函数在词法上位于绑定 table
的 let
内部,因此该函数可以访问该变量的值。
您的代码有一处错误:您应该将 sort
的结果赋值给变量:
(setq list-of-interest (sort list-of-interest ...))
sort
通过重新排列其 cons 单元对列表进行排序,但不能保证将源列表中的第一个 cons 单元重用为目标列表中的第一个 cons 单元。如果您不将结果分配回去,您可能在某些情况下 "lose" 一些列表元素。
我在设计程序时犯了一个错误。 我需要按值对散列 table 中的部分条目进行排序。 我会用演示代码来讲述这个故事。
;; A loacal hash table......
(let ((table (make-hash-table))
(list-of-interest nil))
(puthash 0 "Foo" table)
(puthash 1 "Bar" table)
;;..........
(puthash 9999 "Bra" table)
;; And I have a list with key I am interested to sort
(dotimes (var 50)
(add-to-list list-of-interest (random 9999)))
;; Sorting should depends on comparing the associated string
;; For exmple,
;; If the list is (0 1 9999)
;; I hope to get (1 9999 0) as "Bar" < "Bra" < "Foo"
;; However, I forgot that the table is a local variable
;; I can't pass the table to the predicate function by any means
;; So the predicate function can never resolve the string from the key
(sort list-of-interest 'predicate)
;; When I was thinking to rewrite the code
;; I find that a lambda function can 'grab' the local variable
(sort list-of-interest (lambda (a b)
(string-lessp (gethash a table) (gethash b table))))
;; return value
table)
我在心里提出了两个问题:
- 最重要的问题:lambda函数可以吗?
- 我相信 lambda 是一个像其他函数一样没有名字的函数。为什么它可以'grab'局部变量?
是的,你的 lambda 函数没问题。
Emacs Lisp 有两种类型的绑定:动态绑定和词法绑定。动态绑定是默认设置,您可以通过将此行添加为 Emacs Lisp 源文件的第一行来在每个文件的基础上激活词法绑定:
;;; -*- lexical-binding: t; -*-
(这会将本地缓冲区中的变量 lexical-binding
设置为 t
。)
您的 lambda 函数可以正确处理动态绑定和词法绑定。
它与动态绑定一起工作正常,因为该函数仅在 sort
函数运行时被调用,并且在其执行期间有一个名为 table
的 let-bound 变量,其中包含所需的值.
它与词法绑定一起工作正常,因为该函数在词法上位于绑定 table
的 let
内部,因此该函数可以访问该变量的值。
您的代码有一处错误:您应该将 sort
的结果赋值给变量:
(setq list-of-interest (sort list-of-interest ...))
sort
通过重新排列其 cons 单元对列表进行排序,但不能保证将源列表中的第一个 cons 单元重用为目标列表中的第一个 cons 单元。如果您不将结果分配回去,您可能在某些情况下 "lose" 一些列表元素。