You can use ,@ within any backquote, not only in a macro.
(defun f (x)
`(a b ,@(if x '(c d) (values)) e))
CL-USER> (f nil)
(A B E)
CL-USER> (f t)
(A B C D E)
Greetings.
--
> [TheFlyingDutchman <zzbb...@aol.com>, 2011-02-24 15:09]
>> Is there an equivalent to ,@ if you are not using a backquote in a
>> macro?
>>
>
> You can use ,@ within any backquote, not only in a macro.
>
> (defun f (x)
> `(a b ,@(if x '(c d) (values)) e))
But the OP has asked for an equivalent. In general, the equivalent of
,@ is APPEND:
(defun f (x)
(append '(a b) (if x '(c d) '()) '(e)))
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
(defmacro define-function1 (function_name &optional parameters &rest
body)
`(defun ,function_name ,parameters ,@body)
)
(defmacro define-function2 (function_name &optional parameters &rest
body)
(list 'defun function_name parameters (when body (append nil body)))
)
(format t "define-function1:~%~s~%" (macroexpand-1 '(define-function1
funky (string1 string2)
(substring string1 1 2)
(+ 2 2))
))
(format t "define-function2:~%~s~%" (macroexpand-1 '(define-function2
funky (string1 string2)
(substring string1 1 2) (+ 2 2))
))
---------------------------------------------------------------------
define-function1:
(DEFUN FUNKY (STRING1 STRING2) (SUBSTRING STRING1 1 2) (+ 2 2))
define-function2:
(DEFUN FUNKY (STRING1 STRING2) ((SUBSTRING STRING1 1 2) (+ 2 2)))
I think that should be:
(defmacro define-function1 (function_name parameters &rest body)
`(defun ,function_name ,parameters ,@(when body body)))
That may be what you are *trying* to do, but it's not what you really
want to do. There are several problems with what follows.
> Append doesn't seem to do that:
>
> (defmacro define-function1 (function_name&optional parameters&rest
> body) `(defun ,function_name ,parameters ,@body) )
To start, why did you make parameters optional? If you write
(define-function1 name1 (a) (b))
how is your macro supposed to know whether (a) is the lambda list or
the first form in the body (a call to a function named A)?
> I think that should be:
>
> (defmacro define-function1 (function_name parameters &rest body)
> `(defun ,function_name ,parameters ,@(when body body)))
Why do you think that? What problem are you trying to solve? In any
case, (when body body) == body, so this change doesn't really change
anything.
> (defmacro define-function2 (function_name&optional parameters&rest
> body)
> (list 'defun function_name parameters (when body (append nil
> body))) )
(append nil body) == body
Also, when body is NIL this becomes (append nil nil) == nil. Either way,
you're simply returning a list that is identical to body.
> (format t "define-function1:~%~s~%" (macroexpand-1
> '(define-function1 funky (string1 string2) (substring string1 1 2) (+
> 2 2)) ))
>
> (format t "define-function2:~%~s~%" (macroexpand-1
> '(define-function2 funky (string1 string2) (substring string1 1 2) (+
> 2 2)) ))
>
> ---------------------------------------------------------------------
>
>
define-function1:
> (DEFUN FUNKY (STRING1 STRING2) (SUBSTRING STRING1 1 2) (+ 2 2))
This works as expected...
> define-function2: (DEFUN FUNKY (STRING1 STRING2) ((SUBSTRING STRING1
> 1 2) (+ 2 2)))
I don't see any reason for not using backquote, but assuming you have
one... what you want here is LIST*:
(defmacro define-function2 (name parameters &rest body)
(list* 'defun name parameters body))
Alberto
--
Give a man a fish and he will eat for one day. Teach him programming,
and he will develop a multi tasking intelligent planning algorithm to
optimize the route of a fleet of deep sea fishing boats, with
real-time GPS tracking, weather satellite link, automatic analysis of
fish market prices, the whole thing controlled by an AJAX-enabled web
interface. In the meantime, he will die of hunger.
> (defmacro define-function1 (function_name parameters &rest body)
> `(defun ,function_name ,parameters ,@(when body body)))
No.
> (let ((body nil))
`(defun foo () ,@body))
(defun foo ())
> What I am trying to do it to remove the () around what you get from
> "&rest body". Append doesn't seem to do that:
>
> (defmacro define-function1 (function_name &optional parameters &rest
> body)
> `(defun ,function_name ,parameters ,@body)
> )
In this case what you want is LIST* (note &body and &rest are the same here)
(defmacro define-function1 (fn &optional p &body b)
(list* 'defun fn p b))
You need to stop doing what you do and go to learning about lists -- that
they are made of conses, list manipulation functions, etc. Try writing some
functions using recursion.
You just do not understand how lists work and you try some voodoo magic to
make it work.
It is always wrong, if you're doing it this way you're not learning
anything!
When you will understand how lists work you'll also understand that there is
no magic spell which "removes the ()".
That's good to know as I did think that backquote was only for use
inside a macro.
No, backquote can be used anywhere you need to build a list. It's
especially useful if the list contains many constant symbols (so you
don't need to quote them individually) or you want to make its structure
clear. For example:
(let ((v1 10)
(v2 20))
`(:v1 ,v1 :v2 ,v2))
=> (:v1 10 :v2 20)
I have not really understood all that you have said.
But here are two of observations from my own CL experience
1. why using &rest instead of &body
2. i usually blindly substitute apply instead of funcall whenever I have
to use a &rest value as argument (may not be applicable to what you are
trying to do)
I shall look into the list* stuff Alberto pointed to in another message.
Never used that.
-Antony
They're equivalent in macro lambda lists, but lisp-aware editors can
indent forms differently depending on whether they're defined with &rest
or &body. For instance, look at how LispWorks indents two aliases for
let, one defined with &rest and one with &body. (Even if the editor
isn't aware, human readers expect &body arguments to be "bodies" of
things and &rest arguments to be "a bunch of things".
(defmacro rlet (bindings &rest body)
`(let ,bindings
,@body))
(defmacro blet (bindings &body body)
`(let ,bindings
,@body))
(rlet ((x 1)
(y 2)
(z 3))
(+ x y z)) ; this line is too far to the right
(rlet
((x 1) ; this line is too far to the left
(y 2)
(z 3))
(+ x y z))
(blet ((x 1)
(y 2)
(z 3))
(+ x y z)) ; this line is properly indented
(blet
((x 1) ; farther to the right than the body form
(y 2)
(z 3))
(+ x y z))
//JT
It would help a lot if you read actual documentation on what this thing does
instead of using your weird superstitions you have which are result of
sparse empirical observations.
People like you, who use stuff without even trying to understand it, who
hope that computer will somehow understand what they have meant regardless,
are part of the reason why software sucks as much as it does.
Backquote is just a syntax sugar which essentially transforms backquote
expression into a combination of functions which work with list -- append,
list, cons and stuff like that.
You can find this in CLHS:
http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/sec_2-4-6.html
---
The backquote introduces a template of a data structure to be built. For
example, writing
`(cond ((numberp ,x) ,@y) (t (print ,x) ,@y))
is roughly equivalent to writing
(list 'cond
(cons (list 'numberp x) y)
(list* 't (list 'print x) y))
---
It is not hard to verify this empirically either. Recall that quote quotes
form in verbatim.
Thus if you evaluate '`(foo ,bar ,@baz) it will return internal
representation of `(foo ,bar ,@baz).
But if you do this directly it will look like backquote is a thing of its
own:
* '`(foo ,bar ,@baz)
`(FOO ,BAR ,@BAZ)
But if you recall that in Lisp forms which do something must be lists (the
whole "everything is a list" thing) you'll understand that something is not
quite right.
It might be that implementation beautifies internal representation for you,
and indeed it does.
Now if you set *print-pretty* to NIL:
* (setf *print-pretty* nil)
NIL
You have a chance to see the internal representation:
* '`(foo ,bar ,@baz)
(SB-IMPL::BACKQ-LIST* (QUOTE FOO) BAR BAZ)
It uses SB-IMPL::BACKQ-LIST* in order for printer to know how to beautify
things. But it is equivalent to LIST*, thus in fact that backquote
expression is equivalent to
(LIST* 'FOO BAR BAZ)
You can learn this from documentation too:
http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/sec_2-4-6-1.html
---
Since the exact manner in which the Lisp reader will parse an expression
involving the backquote reader macro is not specified, an implementation is
free to choose any representation that preserves the semantics described.
Often an implementation will choose a representation that facilitates pretty
printing of the expression, so that (pprint `(a ,b)) will display `(a ,b)
and not, for example, (list 'a b). However, this is not a requirement.
---
> T> That's good to know as I did think that backquote was only for use
> T> inside a macro.
>
> It would help a lot if you read actual documentation on what this
> thing does instead of using your weird superstitions you have which
> are result of sparse empirical observations.
> People like you, who use stuff without even trying to understand it,
> who hope that computer will somehow understand what they have meant
> regardless, are part of the reason why software sucks as much as it
> does.
>
> Backquote is just a syntax sugar which essentially transforms
> backquote expression into a combination of functions which work with
> list -- append, list, cons and stuff like that.
It works on vectors too:
* `#(x1 x2 x3 ... xn) may be interpreted to mean (apply #'vector `(x1
x2 x3 ... xn)).
(let ((x 42) (z '(a b))) `#(1 ,x ,@z))
--> #(1 42 A B)