RSS Feed

Lisp Project of the Day

lambda-fiddle

You can support this project by donating at:

Donate using PatreonDonate using Liberapay

lambda-fiddlemacro

Documentation🥺
Docstrings😀
Tests 🥺
Examples🤨
RepositoryActivity🥺
CI 🥺

This library serves a single purpose - to help macro writers to parse lambda lists. In this sense, it is similar to parse-declarations, reviewed on 13 May.

The library has a number of functions to extract or remove exact parts of the lambda list:

POFTHEDAY> (lambda-fiddle:remove-aux-part
            '(foo bar &key baz &aux (something else) altogether))
(FOO BAR &KEY BAZ)

POFTHEDAY> (lambda-fiddle:aux-lambda-vars
            '(foo bar &key baz &aux (something else) altogether))
(SOMETHING ALTOGETHER)

POFTHEDAY> (lambda-fiddle:extract-all-lambda-vars
            '(foo bar &key baz &aux (something else) altogether))
(FOO BAR BAZ SOMETHING ALTOGETHER)

POFTHEDAY> (lambda-fiddle:split-lambda-list
            '(&whole wide world &key roles))
((WORLD) WIDE NIL NIL NIL NIL (ROLES) NIL)

POFTHEDAY> (lambda-fiddle:with-destructured-lambda-list
               (:required req :optional opt)
               '(foo bar &optional baz)
             (list :required req
                   :optional opt))
(:REQUIRED (FOO BAR) :OPTIONAL (BAZ))

It also provides a higher-level macro to extract particular pieces all at once:

POFTHEDAY> (lambda-fiddle:with-destructured-lambda-list
               (:required req :optional opt)
               '(foo bar &optional baz)
             (list :required req
                   :optional opt))
(:REQUIRED (FOO BAR) :OPTIONAL (BAZ))

@Shinmera's "legit" contains a practical example of the with-destructured-lambda-list usage.

This code replaces optional arguments with keywords and adds optional predicates which can be used to check if a keyword argument was provided:

(defmacro define-git-wrapper (name &rest argdefs)
  (lambda-fiddle:with-destructured-lambda-list (:required req :optional opt :key key) argdefs
    (let* ((purereq (purify-args req))
           (purekey (purify-args key))
           (pureopt (purify-args opt))
           (augkeys (mapcar (lambda (a)
                              `(,a NIL ,(p-symb a)))
                            (append pureopt purekey))))
      `(defun ,name (,@purereq &key ,@augkeys)
         (declare (ignorable ,@(mapcar #'third augkeys)))
         (run-git
          ,(subseq (string-downcase name) 4)
          ,@(loop for arg in req 
                  when (front-arg-p arg)
                    collect (parse-rargdef arg))
          ,@(loop for arg in opt
                  when (front-arg-p arg)
                    collect (parse-oargdef arg))
          ,@(mapcar #'parse-kargdef key)
          ,@(loop for arg in req
                  unless (front-arg-p arg)
                    collect (parse-rargdef arg))
          ,@(loop for arg in opt
                  unless (front-arg-p arg)
                    collect
                    (parse-oargdef arg)))))))

That is it. If you want to parse lambda lists, use this little helper instead of searching &optional, &rest, &misc, etc by hand.


Brought to you by 40Ants under Creative Commons License