Parámetros opcionales predeterminados

26

Emacs Lisp no tiene soporte sintáctico para valores predeterminados no nulos de parámetros opcionales. ¿Cuál es el idioma recomendado para suministrar estos parámetros?

Para aclarar mi punto, aquí hay una forma demasiado explícita de hacerlo.

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

¿Cuál, en todo caso, es el estilo recomendado?

Matthew Piziak
fuente

Respuestas:

24

A menos que use extensiones Common Lisp como lo sugiere @legoscia, debe verificar si se especificó el argumento opcional. Tenga en cuenta que realmente no necesita usar letaquí. Esto me parece más idiomático:

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

Como se sugiere en los comentarios, el uso unlesspuede ser preferible a or:

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

También de los comentarios: el estilo funcional más puro sería usar let, como en la pregunta original, pero no necesita nombres de variables separados:

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

Por supuesto, si el parámetro opcional solo se necesita una vez, simplemente debe hacer esto:

(defun my-command (a &optional b)
    (command-body a (or b default)))
glucas
fuente
77
-1: No creo que sea un buen estilo usar una expresión de efectos secundarios como setqen una forma booleana "pura" como or. En mi opinión, whenes definitivamente más apropiado aquí, pero generalmente letes la expresión de elección para establecer o cambiar enlaces locales. IOW, el código original me parece mucho más agradable.
lunaryorn
3
Estoy de acuerdo en que algo así (unless b (setq b default)podría ser mejor. Personalmente, creo que letes redundante aquí porque bya es local para el defun.
glucas
3
Es una cuestión de gustos, pero prefiero código puro y enlaces puros, es decir, letsobre una forma de efectos secundarios como setq. Es el código para un parámetro predeterminado, pero el uso liberal de setqcambiar las variables locales hace que el código sea difícil de leer y seguir. Creo que es mejor considerar todos los enlaces locales inmutables, y solo establecer nuevos enlaces con let. IOW, prefiera un estilo funcional sobre uno imperativo.
lunaryorn
22

Puede usar cl-defun, lo que le permite especificar un valor predeterminado para argumentos opcionales:

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

El valor predeterminado, en este caso default-b, se evaluará cada vez que se llame a la función.

legoscia
fuente