##Scoping
In Emacs Lisp a nesting a defun
inside another defun
does not create a lexically scoped function. The symbol for the 'nested' function is still interned at in the current objarray
. The behavior is unlike that of Scheme.
##Formatting
The formatting of the code within the call to pcase
is difficult to read. When the condition and consequent cannot be listed on the same line, it is probably more common to place the consequent below the conditional.
##Suggested Alternative Format
(defun expand-pattern (pattern)
(mapcar (lambda (tokens)
(mapconcat (lambda (token)
(format "%s" token))
(reverse tokens)
""))
(expat '(()) pattern)))
(defun expat (parents expr)
"Utility function for expand pattern."
(pcase expr
((or (pred stringp)
(pred numberp))
(mapcar (lambda (parent)
(cons expr parent))
parents))
(`(and ,first)
(expat parents first))
(`(and ,first . ,rest)
(expat (expat parents first)
(cons 'and rest)))
(`(or . ,args)
(apply #'append
(mapcar (lambda (arg)
(expat parents arg))
args)))
(_ (error "unknown %S" expr))))
##Other Remarks
Because expat
throws an error, it might make sense to have expand-pattern
invoke expat
within a try...catch
block. Alternatively, expat
could return nil
when no match is found. If nil
is a possible return value from processing the pattern, then a "Lispy" thing to do is to return two values, the first being the result of processing the expression and the second being either nil
or t
to indicate an error or no error.