I made a mistake in designing the program. I need to sort part of the entries in a hash table by their value. I will tell the story with a demo code.
;; 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)
I raised two questions in my mind:
Yes, your lambda function is fine.
Emacs Lisp has two types of binding: dynamic binding and lexical binding. Dynamic binding is the default, and you can activate lexical binding on a per-file basis by adding this line as the very first line of the Emacs Lisp source file:
;;; -*- lexical-binding: t; -*-
(This sets the variable lexical-binding
to t
in the local buffer.)
Your lambda function works correctly with both dynamic and lexical binding.
It works correctly with dynamic binding, because the function is only called while the sort
function runs, and during its execution there is a let-bound variable called table
which contains the desired value.
It works correctly with lexical binding, because the function is lexically inside the let
that binds table
, and therefore the function can access the value of that variable.
There's one thing wrong with your code: you should assign the result of sort
back to the variable:
(setq list-of-interest (sort list-of-interest ...))
sort
sorts the list by rearranging its cons cells, but it's not guaranteed to reuse the first cons cell in the source list as the first cons cell in the target list. If you don't assign the result back, you may in certain situations "lose" some list elements.