25

Emacs Lisp does not have syntactical support for non-nil defaults of optional parameters. What is the recommended idiom for supplying these parameters?

To clarify my point, here is one overly explicit way of doing so.

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

What, if anything, is the recommended style?

21

Unless you use Common Lisp extensions as suggested by @legoscia, you need to check if the optional argument was specified. Note that you don't really need to use let here. This seems more idiomatic to me:

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

As suggested in the comments, using unless may be preferable to or:

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

Also from the comments: the more pure functional style would be to use let, as in the original question, but you don't need separate variable names:

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

Of course, if the optional parameter is only needed once you should just do this:

(defun my-command (a &optional b)
    (command-body a (or b default)))
  • 7
    -1: I don't think that it's good style to use a side-effecting expression like setq in a “pure” boolean form like or. In my opinion when is definitely more appropriate here, but generally let is the expression of choice to establish or change local bindings. IOW, the original code looks much nicer to me. – lunaryorn Jul 23 '15 at 20:46
  • 3
    I agree that something like (unless b (setq b default) might be better. Personally, I think let is redundant here because b is already local to the defun. – glucas Jul 23 '15 at 20:59
  • 3
    It's a matter of taste, but I prefer pure code and pure bindings, i.e. let over a side-effecting form like setq. It's code for a parameter default, but liberal use of setq to change local variables makes code hard to read and to follow. I think it's best to consider all local bindings immutable, and only establish new bindings with let. IOW, prefer a functional style over an imperative one. – lunaryorn Jul 23 '15 at 21:09
20

You can use cl-defun, which lets you specify a default value for optional arguments:

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

The default value, in this case default-b, will be evaluated every time the function is called.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.