Коли слід використовувати різкі цитати?


10

Я бачу, що гострі котирування використовуються в коді eLisp інших людей, і я їх використовую сам, але мені не зовсім зрозуміло, коли вони підходять, а коли ні.

Чи може хто-небудь уточнити, коли саме доречно використовувати різкі цитати та коли замість цього слід використовувати звичайні одиничні лапки?


3
nb Тут є чимало дублікатів цього питання або на SO
phils


1
Я не думаю, що це дублікат: emacs.stackexchange.com/questions/3595 стосується використання #'лямбда (де відповідь в основному "ніколи"), тоді як питання @ izkon стосується скоріше використання #'застосованих до символів.
Стефан

Відповіді:


12

#'це просто скорочення function, як 'і стенографія quote.

Ви можете використовувати його в будь-якому місці, де ви хочете вказати байт-компілятору або інтерпретатору чи читачеві людини, що очікується, що його аргумент стане (трактується як) функцією.

У багатьох контекстах контекст визначає, як трактується аргумент, якщо, наприклад, ви просто цитуєте його (використовуйте quoteабо '), а не використовуєте #'(або function). Наприклад, у контексті, коли символ використовується лише для його symbol-functionвластивості, тобто він використовується як функція, ви можете просто передавати символ (наприклад, цитуючи його або передаючи змінну, значенням якої є символ).

Але іноді код зрозуміліший, якщо ви використовуєте #'в таких контекстах. Навіть якщо Emacs-Lisp сама розуміє, що символ використовується як функція в таких контекстах, це може допомогти підкреслити це для людського читача коду.

У деяких інших Ліпсах обробка форм лямбда, які просто цитуються (з ') або не цитуються, може відрізнятися від їх використання у функціональному положенні при цитуванні за допомогою function( #'). Але не в Emacs Lisp. У Emacs Lisp вам не потрібно цитувати (використовуючи або 'або #') лямбда-форму, яку ви хочете розглядати як функцію (а не просто як список). Якщо ви хочете, щоб його обробляли просто як список, з машиною lambdaтощо, то цитуйте його (разом ') - приклад нижче ілюструє це.

Від (elisp) анонімних функцій :

- Спеціальна форма: function function-object

Ця спеціальна форма повертається, FUNCTION-OBJECTне оцінюючи її.

У цьому він схожий на quote(* примітка Цитування: :). Але на відміну від цього quote, він також слугує приміткою до оцінювача Emacs та байтового компілятора, який FUNCTION-OBJECTпризначений для використання як функції. Якщо припустити FUNCTION-OBJECT, що це дійсний лямбда-вираз, це має два ефекти:

• Коли код FUNCTION-OBJECTкомпілюється в байт , збирається в об'єкт функції байт-коду (* Примітка Компіляція байтів: :).

• Якщо ввімкнено лексичне зв’язування, FUNCTION-OBJECTперетворюється на закриття. * Примітка Закриття ::.

Синтаксис читання #'- це короткий посібник для використання function. Наступні форми є рівнозначними:

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

У наступному прикладі ми визначаємо change-propertyфункцію, яка приймає функцію як третій аргумент, а потім double-property функцію, яка використовує change-propertyпередачу їй анонімної функції:

(defun change-property (symbol prop function)
   (let ((value (get symbol prop)))
     (put symbol prop (funcall function value))))

(defun double-property (symbol prop)
   (change-property symbol prop (lambda (x) (* 2 x))))

Зауважте, що ми не цитуємо lambdaформу.

Якщо ви компілюєте вищевказаний код, також складається анонімна функція. Це не відбудеться, якби, скажімо, ви побудували анонімну функцію, цитуючи її як список:

(defun double-property (symbol prop)
   (change-property symbol prop '(lambda (x) (* 2 x))))

У цьому випадку анонімна функція зберігається як лямбда-вираз у складеному коді. Байтовий компілятор не може вважати, що цей список є функцією, хоча він виглядає як один, оскільки не знає, що change-propertyмає намір використовувати його як функцію.


9

#'(ака function) може використовуватися перед, (lambda ...)але це надлишкове, тому єдине місце, де це дійсно значимо, - перед символом, як в #'car. У Elisp, #'carі 'carмайже повністю еквівалентні, тому одна з основних цілей є просто документувати намір (тобто вказати , хто читає цей код , який ви збираєтеся використовувати цей символ в якості опції). Однак є кілька обставин, коли різниця є більш значною:

  • Байт-компілятор користується цим документально наміченим наміром, і коли ви пишете, #'carвін перевірятиме, чи carіснує функція, і якщо вона не знайде її, він надсилатиме попередження, як і коли б у вас був дзвінок на цю функцію .
  • Всередині cl-fletі cl-labelsлише #'fможна посилатися на локально визначену функцію f, оскільки 'fвона все ще посилатиметься на глобальний символ f(і будь-яка функція може бути збережена у своєму symbol-functionслоті). Напр

    (cl-flet ((car (x y) (+ x y)))
      (list #'car 'car))
    =>
    ((closure nil (x y) (+ x y)) car)
    
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.