cl-defun from cl-macs.el allows you to specify default values (beside much other mind-blowing stuff).
(cl-defun testfun (arg &optional (opt1 1) (opt2 2))
"Process normal ARG and optional args OPT1 and OPT2 with defaults 1 and 2, respectively."
(list arg opt1 opt2))
Test 1: Set opt2 explicitly to nil:
(testfun 1 'a nil)
(1 a nil)
Test 2: Setting ...
The cleanest way IMO is to define an additional variable in the argument list that indicates if the argument was supplied by the caller. This can be done using cl-defun since it supports Common Lisp style argument lists. For example,
(cl-defun test (&optional (x nil supplied-p))
(list x supplied-p))
(test) => (nil nil)
A simple way to differentiate between value nil and a missing optional argument is to use &rest instead of &optional.
I demonstrate that with the following test function:
(defun testfun (arg &rest optArgs)
"Do something with ARG, OPT1, and OPT2.
OPT1 and OPT2 can be nil, 1, and 2.
The default of OPT1 is 1 and the default of 2 is 2.
\(fn ARG &...