between defun and defmacro

Discussion of Common Lisp

between defun and defmacro

Postby greenbeer » Mon Apr 06, 2009 2:53 pm

Hello!
Is it possible in common lisp to write macro which interprets part of arguments like defmacro and other part like defun?
For example, something like:
Code: Select all
(def-amazing-macro leopard (dog &value cat)
  `(if ,dog "war is over" cat))

(let ((x "happy old year"))
  (leopard  (> 4.99 5) x))
;; it should give:
"happy old year"


PS1: i ask you for fun not for studies ;)
PS2: Of course it is easy to write a small language "embedded" in lisp in with it is possible, but I'm looking for more lisp-conventional solution.
Thanks.
greenbeer
 
Posts: 3
Joined: Sun Apr 05, 2009 2:15 am

Re: between defun and defmacro

Postby qbg » Tue Apr 07, 2009 9:16 am

In this case,
Code: Select all
(defmacro leopard (dog cat)
  `(if ,dog "war is over" ,cat))

will do what you want here:
Code: Select all
(let ((x "happy old year"))
  (leopard  (> 4.99 5) x))
;; it should give:
"happy old year"


Though it only works because you don't need to know anything about the variable 'x' at macroexpansion time.
qbg
 
Posts: 64
Joined: Mon Jun 30, 2008 1:05 pm
Location: Minnesota

Re: between defun and defmacro

Postby gugamilare » Tue Apr 07, 2009 11:03 am

If you want a shorthand so that instead of writing ",cat" you can write "cat", well, as an option your macro can be macroexpanded into something like this:

Code: Select all
(defmacro leopard (dog cat*)
      (let ((catg (gensym)))
        `(let ((,catg ,cat*))
      ,(subst catg 'cat
         `(if ,dog "war is over" cat)))))


This is not hygienic at all; maybe you can do better than me.

OTOH, if you are thinking about evaluating the value of the variable "cat" in such a way that the macroexpansion itself can't be done without this value explicitly, then I believe the only way would be to use eval. But this would be just ugly. See http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/c702a580c5acba30/aec455f8fa56951a?q=#aec455f8fa56951a
gugamilare
 
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil

Re: between defun and defmacro

Postby Paul Donnelly » Tue Apr 07, 2009 2:12 pm

greenbeer wrote:Hello!
Is it possible in common lisp to write macro which interprets part of arguments like defmacro and other part like defun?
For example, something like:
Code: Select all
(def-amazing-macro leopard (dog &value cat)
  `(if ,dog "war is over" cat))

(let ((x "happy old year"))
  (leopard  (> 4.99 5) x))
;; it should give:
"happy old year"

No matter what the value of CAT is, you've typed the symbol in a quoted list. Whether CAT is evaluated at macroexpansion time or at run time, you haven't referred to it anywhere. Quasiquoting doesn't have anything to do with macros. It's just shorthand that lets you avoid writing LIST and ' a bunch of times. If you'd written your macro properly, it would behave like you want it to.
Code: Select all
(defmacro leopard (dog cat)
  `(if ,dog "war is over" ,cat))

(macroexpand '(leopard (> 4.99 5) x)) => (IF (> 4.99 5) "war is over" X)

This gives the answer you wanted.

If you just want to ensure that CAT is only evaluated once in the macroexpanded code, or is always evaluated, then return `(LET ((CAT ,CAT)) (IF ,DOG "war is over" CAT)). Note that if the code in DOG refers to any variables named CAT, that binding will be clobbered. You can fix that with a gensym.
Paul Donnelly
 
Posts: 148
Joined: Wed Jul 30, 2008 11:26 pm


Return to Common Lisp

Who is online

Users browsing this forum: Google [Bot], Yahoo [Bot] and 4 guests

cron