Функции высшего порядка в Elisp

Я создал функцию, которая возвращает функцию в Elisp:

(defun singleton-set (elem)
  (defun f (n) (= n elem))
  f)

Я пытаюсь запустить это в IELM, но не получается:

ELISP> (singleton-set 5)
*** Eval error ***  Symbol's value as variable is void: f
ELISP> ((singleton-set 5) 5)
*** Eval error ***  Invalid function: (singleton-set 5)

Из-за В чем разница между Lisp-1 и Lisp-2? я изменил код на

(defun singleton-set (elem)
  (defun f (n) (= n elem))
  #'f)

И вызов (funcall (singleton-set 5) 5), но теперь ошибка

*** Eval error *** Symbol's value as variable is void: elem

Из elisp: захвата переменной из внутренней функции я понимаю, что это происходит из-за динамического связывания Emacs Lisp.

Как сделать возможным в Emacs Lisp функции, возвращающие функции? В чем причина того, что этот механизм отличается от других языков, таких как Python, Scala или Clojure?

Связанные вопросы:


person Mirzhan Irkegulov    schedule 07.10.2012    source источник
comment
возможный дубликат функций elisp в качестве параметров и в качестве возвращаемого значения   -  person Marcin    schedule 08.10.2012
comment
Вы не хотите использовать defun внутри singleton-set. Вместо этого используйте что-нибудь вроде (defun singleton-set (elem) #'(lambda ...)) и посмотрите на указатели @ geocar ниже.   -  person Dale Hagglund    schedule 19.10.2012


Ответы (3)


Из NEWS для Emacs 24:

Изменения Lisp в Emacs 24.1

  • Код теперь может использовать лексическую область видимости по умолчанию вместо динамической области видимости. Переменная lexical-binding включает лексическую область видимости для локальных переменных. Обычно он устанавливается через локальную переменную файла в первой строке файла, и в этом случае он применяется ко всему коду в этом файле.

Итак, в Emacs 24:

(setq lexical-binding t)
(defun singleton-set (elem) (lambda (n) (= n elem)))
(mapcar (singleton-set 1) '(0 1 2 3))
    ===> (nil t nil nil)
person Gareth Rees    schedule 07.10.2012
comment
Мне кажется, что это не использует лексическую привязку - возможно, я что-то упускаю. Я не вижу в коде замыкания. - person Charlie Flowers; 21.03.2014
comment
@CharlieFlowers: Вам что-то не хватает. (Попробуйте включить lexical-binding и выключите, и вы увидите.) elem должен быть лексически привязан, если lambda должен быть вызван вне вызова singleton-set. - person Gareth Rees; 21.03.2014

Как сделать возможным в Emacs Lisp функции, возвращающие функции?

Использование поддельного закрытия и lexical-let.

В чем причина того, что этот механизм отличается от других языков, таких как Python, Scala или Clojure?

Ричард Столмен ответил на этот вопрос в статье, которую написал недавно .

person geocar    schedule 07.10.2012

(defun singleton-set (elem)
  `(lambda (n) (= n ,elem))

См .: функции elisp как параметры и как возвращаемое значение

person Marcin    schedule 07.10.2012