Skip to main content
1 of 2
ceving
  • 413
  • 3
  • 11

Expand string patterns in Elisp

I need to expand logical patterns to list of strings.

For example I have the following definition:

(expand-pattern '(and "xy"
                      (or "1" "2")
                      (or (and "ab0"
                               (or "1" "2" "3"))
                          "cd01")))

Which evaluates to the following list of strings:

("xy1ab01" "xy2ab01" "xy1ab02" "xy2ab02" "xy1ab03" "xy2ab03" "xy1cd01" "xy2cd01")

I wrote the following code:

(defun expand-pattern (pattern)
  (defun expat (parents expr)
    (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))))
  (mapcar (lambda (tokens)
            (mapconcat (lambda (token)
                         (format "%s" token))
                       (reverse tokens)
                       ""))
          (expat '(()) pattern)))

I am new to Emacs Lisp and would like to know, if this is a reasonable way to solve the problem in Elisp or if it can be optimized, to simplify the code.

ceving
  • 413
  • 3
  • 11