(defmacro f_x ...)

TorgoX on 2006-07-05T09:27:01

Dear Log,

Today's inane new elisp macro of mine:

(defmacro f_x (&rest Body)
 "Make these expressions a function with 'x' holding its one parameter"
 (list 'function (cons 'lambda (cons (cons 'x nil) Body))))

So this:

(f_x (print "I like pie and %s" x) (* 3.14 x))

is a handy shorthand that expands to this:

(function (lambda (x) (print "I like pie and %s" x) (* 3.14 x)))


An alternative approach

arc on 2006-07-17T15:20:32

This just came to me; I stole the idea from the implicitly-declared parameters in Perl 6.

(defmacro fn (&rest body)
  (let* ((env (make-hash-table :test 'eq))
         (new-body (fn-expand env `(progn ,@body)))
         (parameters '()))
    (maphash #'(lambda (key &optional value)
                 (setq parameters (cons key parameters)))
             env)
    `(lambda ,(sort parameters #'string-lessp)
       ,@(cdr new-body))))

(defun fn-expand (env body)
  (cond ((symbolp body)
         (when (let ((case-fold-search t))
                 (string-match "^\\^[a-z][-_a-z0-9]*$" (symbol-name body)))
           (puthash body t env))
         body)
        ((and (consp body) (symbolp (car body)))
         (when (eq (car body) 'fn)
           (throw "(fn BODY...) does not yet support nesting"))
         (cons (car body)
               (mapcar #'(lambda (arg) (fn-expand env arg))
                       (cdr body))))
        (t
         body)))

Now you can do things like this:

(fn (print "I like pie and %s" ^x) (* 3.14 ^x))

(mapcar (fn (+ 7 ^x)) list)

(maphash (fn (puthash ^key ^val new-hash)) old-hash)

That last one in particular is something that can't be done with your f_x macro.

Share and enjoy!

Re:An alternative approach

TorgoX on 2006-07-17T22:25:46

WOW! You're hardcore!