Необязательный параметр по умолчанию


26

Emacs Lisp не имеет синтаксической поддержки значений по умолчанию для необязательных параметров. Какова рекомендуемая идиома для предоставления этих параметров?

Чтобы прояснить мою точку зрения, вот один из слишком явных способов сделать это.

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

Какой, если вообще, рекомендуемый стиль?

Ответы:


24

Если вы не используете расширения Common 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, оригинальный код выглядит намного лучше для меня.
lunaryorn

3
Я согласен, что что-то вроде (unless b (setq b default)может быть лучше. Лично я думаю, что letздесь избыточно, потому что bэто уже локально для defun.
глюк

3
Это дело вкуса, но я предпочитаю чистый код и чистые привязки, т. letЕ. Как побочную форму setq. Это код для параметра по умолчанию, но либеральное использование setqдля изменения локальных переменных затрудняет чтение и следование коду. Я думаю, что лучше всего считать все локальные привязки неизменными и устанавливать только новые let. Я хочу отдать предпочтение функциональному стилю, а не императивному.
lunaryorn

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.