Коли різко цитувати лямбдаський вираз?


30

Питання: Коли, якщо коли - небудь, є корисним гострим процитувати lambda, і коли, якщо коли - небудь, ми повинні НЕ гострими процитувати lambda?

Люди використовують lambdas трьома способами:

  1. звичайний: (lambda (x) x)
  2. цитується: '(lambda (x) x)
  3. різко цитується: #'(lambda (x) x)

Цей потік SO обговорює три типи, цей потік SO пояснює, чому не слід цитувати (NB: не гостре цитування ) lambdas, і цей потік SO також обговорює відмінності між цитуванням та різким цитуванням.

Тепер, ручний вузол на анонімних функціях та доктрину для lambdaзауваження, що lambdas самоцитуються:

Дзвінок форми (lambda ARGS DOCSTRING INTERACTIVE BODY)- це самоцитування; результатом оцінки лямбда-виразу є сам вираз. Вираз лямбда може потім трактуватися як функція ...

Отже, виявляється, що (lambda (x) x)і #'(lambda (x) x)є рівнозначними, але '(lambda (x) x)це не так (головне, коли байт-компіляція).

Схоже , що один рідко хочете процитуватиlambda , але незрозуміло мені , коли, якщо коли - небудь, ми повинні або не повинні, з гострими цитую:

  • Чи різке цитування - це lambdaпросто стилістичний вибір, чи існують обставини, коли різке цитування насправді корисне?
  • Чи існують обставини, за яких ми не повинні чітко цитувати a lambda, тобто коли це буде змінювати значення коду?

Відповіді:


28

Колись різка цитата була потрібна лямбдам, тепер це вже не так.

Отже, виявляється, що (лямбда (х) х) і # '(лямбда (х) х) еквівалентні, але' (лямбда (х) х) це не (головне, коли байт-компіляція).

Так. Насправді перші два повністю ідентичні при оцінці. Як описано на сторінці посилання, яку ви пов’язали:

Наступні форми є рівнозначними:

(lambda (x) (* x x)) 
(function (lambda (x) (* x x))) 
#'(lambda (x) (* x x))

Крім спроб підтримати версії Emacs два десятиліття тому, ніколи не виникає причин наголошувати цитату на лямбда.

Тож не варто.


Як сторонне позначення:

  • Жорстке цитування лямбда (з ') все-таки має значення, це перешкоджає компіляції байтів. Я не можу придумати сценарій, де це корисно, але хто знає.

  • Задня частина є єдиною цитатою, яка справді корисна з лямбдами, але лише якщо ви з певних причин не використовуєте лексичні в’язки.


Розглянемо додавання посилання до розділу " Анонімні функції " в посібнику, який містить приклад, що пояснює вплив цитування на компіляцію байтів.
Костянтин

@Constantine Готово. Мені стало ледаче, бо я по телефону, і ОП вже зв’язав це.
Малабарба

Чи можете ви уточнити, що ви маєте на увазі щодо використання не лексичного зв’язування та зворотного зв'язку? Спасибі.
coredump

@coredump За допомогою динамічного прив'язки єдиний спосіб зробити зовнішні змінні доступними всередині лямбда - це вручну створити лямбда як список зі змінною всередині. Задній користь для подібних речей.
Малабарба

До речі, я не думаю, що "колись давно" насправді застосовується: коли я досліджував цю тему в історії ревізій, я виявив, що lambdaце було визначено як макрос, який додає формат functionназад, як я міг піти. IOW якщо #'це було потрібно в якийсь момент, це було в дуже ранньому коді розробки. Це, звичайно, не було потрібне вже в Emacs-18.
Стефан

5

Оскільки lambdaце не має сенсу, коли він не цитується, останні версії Emacs Lisp дотримуються (ANSI) Common Lisp у трактуванні без котирування (lambda...)як #'(lambda...). Обидві позначення майже рівномірно (за винятком цитованої структури).

Чи віддавати перевагу (lambda...)чи #'(lambda...)тому суто питання стилю. Деякі віддають перевагу оголеній формі, яка уникає синтаксичного шуму, а інші (в тому числі я) віддають перевагу цитованій формі.


Це суперечить посібнику elisp: "У Emacs Lisp такий список є дійсним виразом, який визначає об'єкт функції".
djechlin

8
"Останні версії" як і в "версіях, випущених після 1990 року або більше" ;-)
Стефан

0

Додаючи трохи додаткової історії, щоб побачити, чи є історична спадщина # '(лямбда ...)?

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=4290 пропонує:

Починаючи з Emacs 22, lambdaформа складається у байті, коли вона використовується як функція, незалежно від того, передує вона functionчи #'. З версіями Emacs до 22 ви повинні явно використовувати #' або functionякщо ви хочете, щоб форма була складена в байтах.

Я не знаю про компілятор байтів, але я можу бачити, що принаймні до 1993 року lambdaмакрос сам повертав (function (lambda ...))форму.

https://www.iro.umontreal.ca/~monnier/hopl-4-emacs-lisp.pdf також говорить:

Цікаво, що (на відміну від MacLisp) lambdaтехнічно не входив до мови Еліспа приблизно до 1991 року, коли він був доданий як макрос на початку розвитку Emacs-19. У Emacs-18 анонімні функції записувались як цитовані значення форми:

'(lambda (..ARGS..) ..BODY..)

Хоча lambdaмакрос робить цю цитату непотрібною вже майже 30 років, багато випадків цієї практики все ще трапляються в коді Еліспа, хоча це перешкоджає байтовому складенню тіла. Так чи інакше, лише в 1993 році Lucid Emacs 19.8 імпортував #'...читацьку стенографію (function ...)з MacLisp. Emacs пішов за цим роком через рік.


0

Просто хочу навести практичний приклад використання зворотного лямбда-експресії. Йдеться про лексичне зв’язування / змінне затінення, використання зворотного лямбда-виразу та посилання змінних комою дає можливість отримати їх глобальне значення.

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall `(lambda()
             (let ((my-variable "Random"))
               (message ,my-variable)))))

M-x [RET] eval-buffer виходи "Випадкові старі"

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall (lambda()
             (let ((my-variable "Random"))
               (message my-variable)))))

M-x [RET] eval-buffer виходи "Випадкові"

Третій приклад поєднання глобальної змінної та локальної змінної змінної

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall `(lambda()
              (let ((my-variable "Random"))
                (message my-variable)
                (message ,my-variable)))))

M-x [RET] eval-buffer виходи "Випадкові" "Випадкові старі"


@npostavs це було не в моєму прикладі, але я змінив свій приклад, щоб уникнути також поганої практики
cjohansson

Краще, хоча я все ще не впевнений, що це вдосконалення щодо просто вибору іншої назви для внутрішньої прив’язки.
nпостаs
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.