| I have a macro question that needs a bit of context. I'm attempting to build
an object system around closures, translating some code from Doug Hoyte's Let
Over Lambda book [1]. The following macro, dlambda, is given in his book as a
macro that creates a lambda function containing possibly multiple closures. The
lambda function will decide which closure to execute based on the argument
given at evaluation time. I figure this is a pretty cool way to hold state and
even define an "object" abstraction. Here is the macro and an example of using
it: (mac dlambda ds
(w/uniq args
`(fn ,args
(case (car ,args)
,@(mappend
(fn (d)
`(,(if (is t (car d))
t
(car d))
(apply (fn ,@(cdr d))
,(if (is t (car d))
args
`(cdr ,args)))))
ds)))))
(= matt (with (name "matt" age 21)
(dlambda
(name x
(if (no x)
name
(= name (car x))))
(age x
(if (no x)
age
(= age (car x))))
(say words
(prn (string words))))))
(matt 'age)
; => 21
(matt 'name "bob")
; => "bob"
(matt 'name)
; => "bob"
(matt 'say "hello, " "sir")
; => hello, sir
And now I would like to wrap this closure creating ability into a macro that
creates macros for creating these closure objects given a class name and a list
of attributes. Here is my best attempt so far: (def attrfn (attr)
"this takes an attribute name and creates a getter/setter
that can be passed to dlambda. Ex:
arc> (attrfn 'name)
(name x
(if (no x)
name
(= name (car x))))"
(w/uniq arg
`(,attr ,arg
(if (no ,arg)
,attr
(= ,attr (car ,arg))))))
(mac defobject (class attrs)
(with (letargs (mappend [list _ (list 'unquote _)] attrs)
attrfns (map [attrfn _] attrs))
(w/uniq var
`(mac ,class (,var ,attrs)
`(= ,,var (with ,',letargs)
(dlambda
,',@attrfns))))))
A call to (defobject user (name age)) will generate this 'user' macro: arc> (defobject user (name age))
arc> (src user)
(mac user (var62747 (name age))
`(=
,var62747
(with ,'(name ,name age ,age))
(dlambda
,'(name arg62745
(if (no arg62745)
name
(= name (car arg62745)))))))
And finally, trying to create a user will fail like this: (user matt ("matt" 21))
_unquote: undefined;
cannot reference an identifier before its definition
in module: "/Users/matt/code/arc/anarki/ac.scm"
context...:
/Users/matt/code/arc/anarki/ac.scm:1260:4
I know I have been advised (even on this forum) to avoid nested backquotes, but in a macro defining macro, I don't see another way. Thanks in advance for any help![1] http://letoverlambda.com/ Edit: To be clear, I'm not sure if this is something I can fix directly in my code, or if I should approach the problem another way. |