A menos que você use extensões Common Lisp, como sugerido por @legoscia, você precisa verificar se o argumento opcional foi especificado. Observe que você realmente não precisa usar let
aqui. Isso me parece mais idiomático:
(defun command (a &optional b)
(or b (setq b default))
(command-body a b))
Conforme sugerido nos comentários, unless
pode ser preferível usar or
:
(defun command (a &optional b)
(unless b (setq b default))
(command-body a b))
Também a partir dos comentários: o estilo funcional mais puro seria o de usar let
, como na pergunta original, mas você não precisa de nomes de variáveis separados:
(defun my-command (a &optional b)
(let ((b (or b default)))
(command-body a b)))
Obviamente, se o parâmetro opcional for necessário apenas uma vez, você deve fazer isso:
(defun my-command (a &optional b)
(command-body a (or b default)))
setq
em uma forma booleana "pura"or
. Na minha opinião,when
é definitivamente mais apropriado aqui, mas geralmentelet
é a expressão de escolha para estabelecer ou alterar ligações locais. IOW, o código original parece muito melhor para mim.(unless b (setq b default)
pode ser melhor. Pessoalmente, acho quelet
é redundante aqui, porqueb
já é local para odefun
.let
sobre uma forma de efeito colateral comosetq
. É o código para um parâmetro padrão, mas o uso liberal desetq
para alterar variáveis locais torna o código difícil de ler e seguir. Eu acho que é melhor considerar todas as ligações locais imutáveis e apenas estabelecer novas ligações comlet
. IOW, prefira um estilo funcional ao imperativo.Você pode usar
cl-defun
, o que permite especificar um valor padrão para argumentos opcionais:O valor padrão, neste caso
default-b
, será avaliado toda vez que a função for chamada.fonte