(defmacro fo(text)
(list 'format t "~A" text))
(defun fo(text)
(eval (list 'format t "~A" text)))
should i use a function or a macro for this and why? both works and if
so i should use a function?
when profiling with time they both take 0.0 seconds and defmacro takes
528bytes and defun takes 428bytes.
when running with a longer text i notice the macro takes a little time
sometimes(i mean basically no time anyway so not that it matters).
globalrev <·········@yahoo.se> writes:
> (defmacro fo(text)
> (list 'format t "~A" text))
>
> (defun fo(text)
> (eval (list 'format t "~A" text)))
>
>
> should i use a function or a macro for this and why? both works and if
> so i should use a function?
You should use a function for this, because (A) the function is shorter,
(B) macros run when your code is compiled, not when the compiled code is
run, and (C) arguments to functions are evaluated before the function
gets them, but arguments to macros are passed in as read.
(A) The function would be shorter if you had written it right. Why did
you think you needed to call EVAL on a list of code in order to call
FORMAT?
(defun fo (text)
(format t "~A" text))
(C) When you call the function FO, its argument is evaluated before it
is passed to FO.
(fo "text") ; will call FO with the string "text" as an argument.
(let ((tx "text")) ; does the same, since TX is evaluated
(fo tx)) ; before FO is called.
When you call the macro FO, its argument is NOT evaluated
beforehand. All arguments to macros are passed to the macro EXACTLY as
the reader would read them. Try typing (READ) into your REPL, then
typing the argument you hoped to use with your macro, then pressing
"return". Unless the result is the data you were hoping your macro would
operate on, you need to re-think your approach. MACROEXPAND is another
very useful function for debugging macros.
(fo "text") ; will call FO with the string "text" as an argument.
(let ((tx "text")) ; calls it with the symbol TX, since TX does not
(fo tx)) ; get evaluated before FO is called.
(B) It's very important to know when your code gets run. Functions run
at run-time, so they can operate on values only known at run-time.
Macros run before your code even gets compiled, and their sole purpose
is to return new code to be substituted in their place. Unless you want
to do that, don't use a macro.
MACROEXPAND will let you see the return value of your macro.
(macroexpand '(fo "text"))
=> (FORMAT T "~A" "text")
In this case, the only reasons not to use a macro are that it is more
complicated to write and you need to recompile any code that uses it
when the macro is changed. For more complicated code, the cut-and-paste
nature of macros will have unintended consequences.
Since your macro was correctly written, the results were as
intended. The macro FO was replaced by a call to FORMAT with FO's
argument substituted into the FORMAT call. It's not buggy, merely
stylistically addled.
P.S. Your formatting is weird. Normally we would type:
(defun fo (text)
(format t "~A" text))
(defmacro fo (text)
(list 'format t "~A" text))
On 28 Apr, 08:02, Paul Donnelly <·············@sbcglobal.net> wrote:
> globalrev <·········@yahoo.se> writes:
> > (defmacro fo(text)
> > (list 'format t "~A" text))
>
> > (defun fo(text)
> > (eval (list 'format t "~A" text)))
>
> > should i use a function or a macro for this and why? both works and if
> > so i should use a function?
>
> You should use a function for this, because (A) the function is shorter,
> (B) macros run when your code is compiled, not when the compiled code is
> run, and (C) arguments to functions are evaluated before the function
> gets them, but arguments to macros are passed in as read.
>
> (A) The function would be shorter if you had written it right. Why did
> you think you needed to call EVAL on a list of code in order to call
> FORMAT?
>
> (defun fo (text)
> (format t "~A" text))
>
> (C) When you call the function FO, its argument is evaluated before it
> is passed to FO.
>
> (fo "text") ; will call FO with the string "text" as an argument.
>
> (let ((tx "text")) ; does the same, since TX is evaluated
> (fo tx)) ; before FO is called.
>
> When you call the macro FO, its argument is NOT evaluated
> beforehand. All arguments to macros are passed to the macro EXACTLY as
> the reader would read them. Try typing (READ) into your REPL, then
> typing the argument you hoped to use with your macro, then pressing
> "return". Unless the result is the data you were hoping your macro would
> operate on, you need to re-think your approach. MACROEXPAND is another
> very useful function for debugging macros.
>
> (fo "text") ; will call FO with the string "text" as an argument.
>
> (let ((tx "text")) ; calls it with the symbol TX, since TX does not
> (fo tx)) ; get evaluated before FO is called.
>
> (B) It's very important to know when your code gets run. Functions run
> at run-time, so they can operate on values only known at run-time.
> Macros run before your code even gets compiled, and their sole purpose
> is to return new code to be substituted in their place. Unless you want
> to do that, don't use a macro.
>
> MACROEXPAND will let you see the return value of your macro.
>
> (macroexpand '(fo "text"))
> => (FORMAT T "~A" "text")
>
> In this case, the only reasons not to use a macro are that it is more
> complicated to write and you need to recompile any code that uses it
> when the macro is changed. For more complicated code, the cut-and-paste
> nature of macros will have unintended consequences.
>
> Since your macro was correctly written, the results were as
> intended. The macro FO was replaced by a call to FORMAT with FO's
> argument substituted into the FORMAT call. It's not buggy, merely
> stylistically addled.
>
> P.S. Your formatting is weird. Normally we would type:
>
> (defun fo (text)
> (format t "~A" text))
>
> (defmacro fo (text)
> (list 'format t "~A" text))
ty veru much.
about the intendation, if u want to go up against this guy go ahead:
http://stuff.mit.edu/afs/net/user/tytso/linux/coding-standards
Date: Fri, 3 Feb 1995 12:38:51 +0200
From: Linus Torvalds <··············@cs.helsinki.fi>
- intendation is hard-tabs, 8 character wide.
1) This makes it obvious at a glance how the code is indented.
2 characters is *much* too small, and 4 characters isn't enough
over 40 lines of code or so, especially if you don't have 40
lines on your screen.
;)
im using lispbox(slime+cbsl+emacs) and i just used what happened when
i tabbed.
globalrev <·········@yahoo.se> writes:
> On 28 Apr, 08:02, Paul Donnelly <·············@sbcglobal.net> wrote:
>> globalrev <·········@yahoo.se> writes:
>> > (defmacro fo(text)
>> > (list 'format t "~A" text))
>>
>> > (defun fo(text)
>> > (eval (list 'format t "~A" text)))
>> [...]
>> P.S. Your formatting is weird. Normally we would type:
>>
>> (defun fo (text)
>> (format t "~A" text))
>>
>> (defmacro fo (text)
>> (list 'format t "~A" text))
>
> ty veru much.
>
>
> about the intendation, if u want to go up against this guy go ahead:
No, it wasn't about indentation, but about a space betwen fo and (text).
Historically, lists were written as:
(a,b,c,d)
this allowed to put spaces in symbol names:
(blue cat,yellow dog,(a,little,smurf),red zebra)
was a list of three symbols.
That was a very very long time ago.
And then it occured to some Great one that it would be better to avoid
spaces in symbol names, and on the countrary, to use spaces to
separate list items, so they started to write:
(blue-cat yellow-dog (a little smurf) red-zebra)
So in a way, writting (defun fo(text)) is like you missed a comma in
the vestigal list.
Now, what matters to the reader is whether the character is a
terminating or non-terminating macro-character. #\( is a terminating
macro-character, so there's no problem if you skip a space, but do you
know by heart what of these other characters
!"#$%&'()*+,-./;<=>·@[]^_`{}~
are also terminating macro-characters?
I thought so, therefore it's better to put a space.
(values
(length '(abc[def]))
(length '(abc [def]))
(length '(abc(def)))
(length '(abc (def))))
-->
1 ;
2 ;
2 ;
2
--
__Pascal Bourguignon__
···@informatimago.com (Pascal J. Bourguignon) writes:
> macro-character, so there's no problem if you skip a space, but do you
> know by heart what of these other characters
> !"#$%&'()*+,-./;<=>·@[]^_`{}~
> are also terminating macro-characters?
I get the impression *you* do. ;)
Chris Barts <··············@gmail.com> writes:
> ···@informatimago.com (Pascal J. Bourguignon) writes:
>
>> macro-character, so there's no problem if you skip a space, but do you
>> know by heart what of these other characters
>> !"#$%&'()*+,-./;<=>·@[]^_`{}~
>> are also terminating macro-characters?
>
> I get the impression *you* do. ;)
No, I'd only guess, or I'd ask my REPL. In addition, it can be
changed dynamically in the readtable.
Ok, let's have some fun, here what I believe:
terminating "'();`
non-terminating !#$%&*+,-./<=>·@[]^_{}~\|
I've added \ and | which I didn't cite originally I don't know why
after all.
Let's try it with the default readtable:
(let ((*readtable* (copy-readtable nil)))
(every (lambda (ch) (eq 'a (read-from-string (format nil "A~C" ch)))) "\"'();`"))
--> T
so far so good
(let ((*readtable* (copy-readtable nil)))
(find-if-not (lambda (ch) (not (eq 'a (read-from-string (format nil "A~C" ch))))) "!#$%&*+,-./<=>·@[]^_{}~\\|"))
--> #\,
oops, I missed comma as terminating macro character.
(let ((*readtable* (copy-readtable nil)))
(every (lambda (ch) (not (eq 'a (read-from-string (format nil "A~C |" ch))))) "!#$%&*+-./<=>·@[]^_{}~\\|"))
--> T
ok.
So I wasn't sure about comma, but obviously, like backquote it's a
terminating macro character in the standard readtable..
;-)
--
__Pascal Bourguignon__
globalrev <·········@yahoo.se> writes:
> (defmacro fo(text)
> (list 'format t "~A" text))
>
> (defun fo(text)
> (eval (list 'format t "~A" text)))
Don't use EVAL. There's no reason this can't be a regular function call.
(defun fo (text)
(format t "~A" text))
> should i use a function or a macro for this and why? both works and if
> so i should use a function?
No, the two do very different things. In the case of a macro:
(fo x)
would macroexpand to
(format t "~A" x)
and be compiled as that call, where x is lexically visible, so that
(let ((y 3))
(let ((x 'y))
(fo x)))
would work and would print Y. By contrast, with your definition
using EVAL,
(let ((y 3))
(let ((x 'y))
(fo x)))
would pass Y to FO at runtime, causing it to do
(eval (list 'format t "~A" 'y))
which would then evaluate (format t "~A" y) in the null lexical environment
(since EVAL has no access to the lexical environment) and should yield an
unbound variable for Y, since Y is lexically bound, not special bound.
> when profiling with time they both take 0.0 seconds and defmacro takes
> 528bytes and defun takes 428bytes.
This is the wrong kind of analysis to do, in part because you should
not be calling EVAL, but also because making your programming
decisions based on profiling is almost always going to lead you
astray. Learn good style and defer profiling until you need
it... which in many cases will not happen, but when it does, you can
do based on delivery needs that may not be apparent at development time.
> when running with a longer text i notice the macro takes a little time
> sometimes(i mean basically no time anyway so not that it matters).
I don't know what a "longer text" is. Is that a string with more
characters? You don't even show an example of a call.