Valeurs par défaut des paramètres facultatifs

26

Emacs Lisp ne prend pas en charge la syntaxe des valeurs par défaut non nulles des paramètres facultatifs. Quel est l'idiome recommandé pour fournir ces paramètres?

Pour clarifier mon propos, voici une manière trop explicite de le faire.

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

Quel est, le cas échéant, le style recommandé?

Matthew Piziak
la source

Réponses:

24

À moins que vous n'utilisiez des extensions Common Lisp comme suggéré par @legoscia, vous devez vérifier si l'argument facultatif a été spécifié. Notez que vous n'avez pas vraiment besoin d'utiliser letici. Cela me semble plus idiomatique:

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

Comme suggéré dans les commentaires, l'utilisation unlesspeut être préférable à or:

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

Toujours d'après les commentaires: le style fonctionnel le plus pur serait d'utiliser let, comme dans la question d'origine, mais vous n'avez pas besoin de noms de variables séparés:

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

Bien sûr, si le paramètre facultatif n'est nécessaire qu'une fois, vous devez simplement le faire:

(defun my-command (a &optional b)
    (command-body a (or b default)))
glucas
la source
7
-1: Je ne pense pas que ce soit un bon style d'utiliser une expression à effets secondaires comme setqdans une forme booléenne «pure» comme or. À mon avis, whenc'est certainement plus approprié ici, mais c'est généralement letl'expression du choix d'établir ou de modifier les liaisons locales. IOW, le code original me semble beaucoup plus agréable.
lunaryorn
3
Je suis d'accord que quelque chose comme ça (unless b (setq b default)pourrait être mieux. Personnellement, je pense que letc'est redondant ici parce que bc'est déjà local au defun.
glucas
3
C'est une question de goût, mais je préfère le code pur et les liaisons pures, c'est- letà- dire plutôt qu'une forme à effets secondaires comme setq. C'est le code d'un paramètre par défaut, mais l'utilisation généreuse de setqpour changer les variables locales rend le code difficile à lire et à suivre. Je pense qu'il est préférable de considérer toutes les liaisons locales comme immuables et d'établir uniquement de nouvelles liaisons avec let. IOW, préférez un style fonctionnel à un impératif.
lunaryorn
22

Vous pouvez utiliser cl-defun, ce qui vous permet de spécifier une valeur par défaut pour les arguments facultatifs:

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

La valeur par défaut, dans ce cas default-b, sera évaluée à chaque appel de la fonction.

legoscia
la source