From: Sebastian Tennant on 26 Feb 2010 20:58 Hi all, I don't really understand why this is: CL-USER> (defmacro foo (pair) (funcall (car pair) (cadr pair))) FOO CL-USER> (defun bar (arg) arg) BAR CL-USER> (foo (bar "baz")) "baz" CL-USER> (let ((baz (lambda (arg) arg))) (foo (baz "quux"))) ; in: LAMBDA NIL ; (FOO (BAZ "quux")) ; ; caught ERROR: ; (in macroexpansion of (FOO (BAZ "quux"))) ; (hint: For more precise location, try *BREAK-ON-SIGNALS*.) ; The function BAZ is undefined. ; (LET ((BAZ (LAMBDA (ARG) ARG))) ; (FOO (BAZ "quux"))) ; ; caught STYLE-WARNING: ; The variable BAZ is defined but never used. ; ; compilation unit finished ; caught 1 ERROR condition ; caught 1 STYLE-WARNING condition Execution of a form compiled with errors. I understand that macro arguments aren't evaluated, i.e., that they manipulate s-expressions, not runtime values, but does this really mean there is no way of using an anonymous function in a macro? I'd have thought binding baz to the anonymous function beforehand would get around the above restrictions. Any hints or explanations much appreciated. Seb -- Emacs' AlsaPlayer - Music Without Jolts Lightweight, full-featured and mindful of your idyllic happiness. http://home.gna.org/eap
From: refun on 26 Feb 2010 21:27 In article <sk8njv6w.fsf(a)vps203.linuxvps.org>, sebyte(a)smolny.plus.com says... > > Hi all, > > I don't really understand why this is: > > CL-USER> (defmacro foo (pair) > (funcall (car pair) (cadr pair))) > FOO > CL-USER> (defun bar (arg) arg) > BAR > CL-USER> (foo (bar "baz")) > "baz" > CL-USER> (let ((baz (lambda (arg) arg))) > (foo (baz "quux"))) > ; in: LAMBDA NIL > ; (FOO (BAZ "quux")) > ; > ; caught ERROR: > ; (in macroexpansion of (FOO (BAZ "quux"))) > ; (hint: For more precise location, try *BREAK-ON-SIGNALS*.) > ; The function BAZ is undefined. > > ; (LET ((BAZ (LAMBDA (ARG) ARG))) > ; (FOO (BAZ "quux"))) > ; > ; caught STYLE-WARNING: > ; The variable BAZ is defined but never used. > ; > ; compilation unit finished > ; caught 1 ERROR condition > ; caught 1 STYLE-WARNING condition > Execution of a form compiled with errors. > > I understand that macro arguments aren't evaluated, i.e., that they manipulate > s-expressions, not runtime values, but does this really mean there is no way of > using an anonymous function in a macro? > > I'd have thought binding baz to the anonymous function beforehand would get > around the above restrictions. > > Any hints or explanations much appreciated. > > Seb I'm a bit confused about what you want to do. Your FOO macro attempts to FUNCALL the car of your pair argument at COMPILE- time. While this is possible, it's usually a bad idea, as you may be causing side-effects at compile-time. Macros should usually be used as functional (non- side-effecting) code transformations. So you could for example write something like: (defmacro foo (&body body) `(funcall ,@body)) and have FOO expand into a FUNCALL. (foo (lambda (x) (1+ x)) 9) expands to (FUNCALL (LAMBDA (X) (1+ X)) 9) which evaluates to 10. (foo #'bar "baz") ;=> "baz" (flet ((baz (x) x)) (foo #'baz "quux")) ;=> "quux" I don't see much practical purpose for this, except to define synonyms to functions, but this is far from a an ideal way to do it. Can you elaborate on what exactly is it that you want to do?
From: Pascal J. Bourguignon on 26 Feb 2010 21:29 Sebastian Tennant <sebyte(a)smolny.plus.com> writes: > Hi all, > > I don't really understand why this is: > > CL-USER> (defmacro foo (pair) > (funcall (car pair) (cadr pair))) > FOO > CL-USER> (defun bar (arg) arg) > BAR > CL-USER> (foo (bar "baz")) > "baz" Notice that: C/USER[11]> (macroexpand '(foo (bar "baz"))) "baz" ; T That is, the call to BAR is made at macro-expansion time. If the function BAR had not be defined at the REPL, but in a file, it wouldn't be defined at compilation time, and therefore not at macro-expansion time, and the execution of the macro FOO would have failed. Also, macroexpansion may occur several time, and therefore the function BAR may be called several times. On the other hand, the expansion is "baz" itself, therefore once the macro FOO is expanded, the function BAR is never called at run-time. > CL-USER> (let ((baz (lambda (arg) arg))) > (foo (baz "quux"))) > ; in: LAMBDA NIL > ; (FOO (BAZ "quux")) > ; > ; caught ERROR: > ; (in macroexpansion of (FOO (BAZ "quux"))) > ; (hint: For more precise location, try *BREAK-ON-SIGNALS*.) > ; The function BAZ is undefined. > > ; (LET ((BAZ (LAMBDA (ARG) ARG))) > ; (FOO (BAZ "quux"))) > ; > ; caught STYLE-WARNING: > ; The variable BAZ is defined but never used. > ; > ; compilation unit finished > ; caught 1 ERROR condition > ; caught 1 STYLE-WARNING condition > Execution of a form compiled with errors. > > I understand that macro arguments aren't evaluated, i.e., that they manipulate > s-expressions, not runtime values, but does this really mean there is no way of > using an anonymous function in a macro? Read again the error message! > ; The function BAZ is undefined. And read again the warning! > ; The variable BAZ is defined but never used. You cannot say that clisp doesn't try all it can to tell you there's a problem with BAZ... The problem is that BAZ is a lexical variable, and even when the LET form is typed at the REPL, lexical variables don't exist during macroexpansion. This has nothing to do with the fact that it will eventually be bound to an anonymous function, but just with the fact that it will be bound LATER. > I'd have thought binding baz to the anonymous function beforehand would get > around the above restrictions. You're wrong, it's not bound beforehand. 1- a form is read. 2- a form is compiled. 2.1- a form is macroexpanded (during minimal compilation) 2.2- the code for the form is generated. 3- a form is executed 3.1- a LET form binds variables. .... > Any hints or explanations much appreciated. Your macro is wrong and senseless. What do you want to archieve? -- __Pascal Bourguignon__
From: Ron Garret on 27 Feb 2010 14:41 In article <sk8njv6w.fsf(a)vps203.linuxvps.org>, Sebastian Tennant <sebyte(a)smolny.plus.com> wrote: > Hi all, > > I don't really understand why this is: > > CL-USER> (defmacro foo (pair) > (funcall (car pair) (cadr pair))) > FOO > CL-USER> (defun bar (arg) arg) > BAR > CL-USER> (foo (bar "baz")) > "baz" > CL-USER> (let ((baz (lambda (arg) arg))) > (foo (baz "quux"))) > ; in: LAMBDA NIL > ; (FOO (BAZ "quux")) > ; > ; caught ERROR: > ; (in macroexpansion of (FOO (BAZ "quux"))) > ; (hint: For more precise location, try *BREAK-ON-SIGNALS*.) > ; The function BAZ is undefined. > > ; (LET ((BAZ (LAMBDA (ARG) ARG))) > ; (FOO (BAZ "quux"))) > ; > ; caught STYLE-WARNING: > ; The variable BAZ is defined but never used. > ; > ; compilation unit finished > ; caught 1 ERROR condition > ; caught 1 STYLE-WARNING condition > Execution of a form compiled with errors. > > I understand that macro arguments aren't evaluated, i.e., that they > manipulate s-expressions, not runtime values, You apparently do not understand this because in your example the anonymous function to which BAZ is bound, and which you are trying to invoke in your expansion of FOO, is a run-time value. (BTW, you should not feel bad about not understanding this. It's a very tricky and subtle issue.) > but does this really mean there is no way of > using an anonymous function in a macro? No, it does not mean that. It doesn't even mean that there is no way to use an anonymous function created at run-time (which is not the same thing, but which is what you are actually doing in your example) in a macro. But it is tricky. > I'd have thought binding baz to the anonymous function beforehand would get > around the above restrictions. > > Any hints or explanations much appreciated. You have to achieve clarity about the order in which various things happen, and in particular, when BAZ is bound, and when FOO is expanded. In your example above, FOO expanded *before* BAZ is bound, which is why you get the error you do. Figuring out how to make this work is non-trivial. The real answer can be found here: http://p-cos.net/documents/hygiene.pdf But if you find that paper impenetrable and you are interested in pursuing this let me know. It's on my agenda to write a more gently introduction to this issue, and if I knew someone was interested that would be motivation to bump it up in the queue. rg
From: Sebastian Tennant on 2 Mar 2010 08:16 Many thanks to all respondents. Some very clear and helpful explanations, shedding light on the considerable gaps in my understanding. Ron, I'd definitely like to read your treatment on the issue. Your Complete Idiot's Guide to Common Lisp Packages was very illuminating. Regards, Sebastian
|
Pages: 1 Prev: another frustrating learner question, CLOS Next: weird GASP error using LUSH |