Let's write β

プログラミング中にできたことか、思ったこととか

正規表現でmatchをつかってcond

正規表現でマッチしたときだけ、式を実行したいときってありますよね。
ただ、二回チェックするのは冗長なので、cond風に書きたいですね。
そこでマクロです。

(defmacro aif-match (regex str then-expr &optional (else-expr nil))
  (if (stringp regex)
    `(multiple-value-bind (match regs) (ppcre:scan-to-strings ,regex ,str)
       (if match
         ,then-expr
         ,else-expr))
    then-expr))
    
(defmacro match-cond (str conds)
  (when conds
    (let ((first-cond (car conds)))
      `(aif-match ,(car first-cond) ,str
                  ,@(cdr first-cond)
                  (match-cond ,str ,(cdr conds))))))

Usage:

(match-cond "create-users-table"
 (("create-(.*)-btable" 1)
  ("create-(.*)-table" (aref regs 0))
  (t 13)))
=> "users"

(match-cond "create-users-table"
 (("create-(.*)-btable" 1)
  ("create-(.*)-tabele" (aref regs 0))
  (t 13)))
=> 13