Необов’язкові параметри за замовчуванням


26

Emacs Lisp не має синтаксичної підтримки для ненульових стандартних параметрів необов'язкових параметрів. Яка рекомендована ідіома для подання цих параметрів?

Щоб уточнити мою думку, ось один із надто явних способів цього зробити.

(defun command (a &optional supplied-b)
  (let ((b (or supplied-b default-b)))
    (command-body a b)))

Що, якщо що, є рекомендованим стилем?

Відповіді:


24

Якщо ви не використовуєте поширені розширення Lisp, як запропонував @legoscia, вам потрібно перевірити, чи вказаний необов'язковий аргумент. Зауважте, що вам не потрібно letтут користуватися. Мені це здається ідіоматичнішим:

(defun command (a &optional b)
  (or b (setq b default))
  (command-body a b))

Як запропоновано в коментарях, використання unlessможе бути кращим для or:

(defun command (a &optional b)
  (unless b (setq b default))
  (command-body a b))

Також з коментарів: більш чистим функціональним стилем було б користуватися let, як в оригінальному питанні, але вам не потрібні окремі назви змінних:

(defun my-command (a &optional b)
  (let ((b (or b default)))
    (command-body a b)))

Звичайно, якщо необов'язковий параметр потрібен лише один раз, ви повинні просто зробити це:

(defun my-command (a &optional b)
    (command-body a (or b default)))

7
-1: Я не думаю, що в хорошому стилі використовувати побічний вираз, як setqу "чистому" булевій формі, як or. На мою думку, whenтут, безумовно, більше підходить, але загалом letце вираження вибору встановити або змінити місцеві прив’язки. IOW, оригінальний код мені виглядає набагато приємніше.
місячник

3
Я згоден, що щось на кшталт (unless b (setq b default)може бути кращим. Особисто я вважаю letзайвим тут, тому що bце вже локально defun.
глюкас

3
Це питання смаку, але я віддаю перевагу чистому коду та чистим прив’язкам, тобто letнад побічною формою на зразок setq. Це код за замовчуванням для параметра, але ліберальне використання setqдля зміни локальних змінних робить код важким для читання та слідування. Я думаю, що найкраще вважати всі локальні прив’язки незмінними, а лише встановлювати нові прив'язки let. IOW, віддайте перевагу функціональному стилю над імперативним.
місячник

22

Ви можете використовувати cl-defun, що дозволяє вказати значення за замовчуванням для необов'язкових аргументів:

(cl-defun command (a &optional (b default-b))
  (command-body a b))

У цьому випадку значення за замовчуванням default-bбуде оцінюватися кожного разу, коли функція викликається.

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