I'm quite new to lisp, but I started writing a bit of code... Things are getting on well (at least, it's working) but I didn't use any macro yet... I'm reading Paul Graham's "On Lisp" which I find great, but I'm still not very at ease with macros. He writes that macros are made to transform expressions... So I thought "let's write a small macro for my needs" : I would like to extend classic arithmetic operations to sequences... for example (my-macro 'list (+ '(1 2 3) #(3 2 1))) would return (4 4 4), but also (my-macro 'vector (+ '(1 2 3) 5)) would return #(6 7 8) and (my-macro 'list (+ '(1 2 3) (* 5 '(1 2 3)))) would return (6 12 18)
so, take Paul Graham's method, I would write what I'll have to type : * (my-macro 'list (+ number1 sequence2 (* sequence3 number4)))
but honestly I really don't know how to write the macro after that... The most mysterious part for me is how to transform the sequences in the original expression into variables for the lambda function...
Martin Raspaud <martin.rasp...@wanadoo.fr> writes: > I'm quite new to lisp, but I started writing a bit of code... Things > are getting on well (at least, it's working) but I didn't use any > macro yet... I'm reading Paul Graham's "On Lisp" which I find great, > but I'm still not very at ease with macros.
Hmm, are you sure you're ready for "On Lisp" yet? Most lisp programmers (myself included) dive into macros a little to early.
> made to transform expressions... So I thought "let's write a small > macro for my needs" : I would like to extend classic arithmetic > operations to sequences... for example > (my-macro 'list (+ '(1 2 3) #(3 2 1))) would return (4 4 4), but also > (my-macro 'vector (+ '(1 2 3) 5)) would return #(6 7 8) and > (my-macro 'list (+ '(1 2 3) (* 5 '(1 2 3)))) would return (6 12 18)
I guess the only point of using a macro here would be to replace the + and * with something else? I don't think that's a very good idea, especially since you have operators that almost match what you want to do:
Here's a little idea: Why not go for something completely different? You can use a generic function instead to extend the behaviour of map the way you want:
> Martin Raspaud <martin.rasp...@wanadoo.fr> writes:
>>I'm quite new to lisp, but I started writing a bit of code... Things >>are getting on well (at least, it's working) but I didn't use any >>macro yet... I'm reading Paul Graham's "On Lisp" which I find great, >>but I'm still not very at ease with macros.
> Hmm, are you sure you're ready for "On Lisp" yet? Most lisp programmers > (myself included) dive into macros a little to early.
>>made to transform expressions... So I thought "let's write a small >>macro for my needs" : I would like to extend classic arithmetic >>operations to sequences... for example >>(my-macro 'list (+ '(1 2 3) #(3 2 1))) would return (4 4 4), but also >>(my-macro 'vector (+ '(1 2 3) 5)) would return #(6 7 8) and >>(my-macro 'list (+ '(1 2 3) (* 5 '(1 2 3)))) would return (6 12 18)
> I guess the only point of using a macro here would be to replace > the + and * with something else? I don't think that's a very good > idea, especially since you have operators that almost match what > you want to do:
> Here's a little idea: Why not go for something completely different? > You can use a generic function instead to extend the behaviour of > map the way you want:
Well, that would work for binary operators, but what if I want something like (my-map 'list #* list1 number2 list 3 number4 number5 list6 list7) or even more ?
Martin Raspaud <martin.rasp...@wanadoo.fr> writes: > Well, that would work for binary operators, but what if I want > something like (my-map 'list #* list1 number2 list 3 number4 number5 > list6 list7) or even more ?
Well, in that case at least I'm pretty sure you won't be able to do much fun with a macro, since the decision on what to do will have to be done at run time (you don't know if the parameters are sequences or numbers until run time). You could probably write my-map as a function that sorted numbers from sequences, used #'map on the sequences and then treated the numbers. -- (espen)
>> Martin Raspaud <martin.rasp...@wanadoo.fr> writes:
>>> I'm quite new to lisp, but I started writing a bit of code... Things >>> are getting on well (at least, it's working) but I didn't use any >>> macro yet... I'm reading Paul Graham's "On Lisp" which I find great, >>> but I'm still not very at ease with macros.
>> Hmm, are you sure you're ready for "On Lisp" yet? Most lisp programmers >> (myself included) dive into macros a little to early.
> Yep maybe, but better soon than never ;-)
Well, I think the point was not never to use them, but not to dive in to macros just for the sake of using macros. But I like your damn-the-torpedos attitude, so...
Methinks one problem is that the macro will only see the source, and I wager you would like to use more than literals with your little hack. So something like:
...well, needs more than luck, it needs run-time dispatch (in some form or other) based on the types of the objects bound to op1 and op2. A macro could expand into all the same dispatching source that would go into a function, but there is no point in that.
As for the GF's espen proposed only working where there are two operands, check out REDUCE. But then you have the problem of generating methods for each permutation:
(my+ number sequence) (my+ sequence number)
..etc. This is where you could use a macro to take one definition and have it write the permutations.
>>> Martin Raspaud <martin.rasp...@wanadoo.fr> writes:
>>>> I'm quite new to lisp, but I started writing a bit of code... Things >>>> are getting on well (at least, it's working) but I didn't use any >>>> macro yet... I'm reading Paul Graham's "On Lisp" which I find great, >>>> but I'm still not very at ease with macros.
>>> Hmm, are you sure you're ready for "On Lisp" yet? Most lisp programmers >>> (myself included) dive into macros a little to early.
>> Yep maybe, but better soon than never ;-)
> Well, I think the point was not never to use them, but not to dive in to > macros just for the sake of using macros. But I like your > damn-the-torpedos attitude, so...
> Methinks one problem is that the macro will only see the source, and I > wager you would like to use more than literals with your little hack. So > something like:
> ...well, needs more than luck, it needs run-time dispatch (in some form > or other) based on the types of the objects bound to op1 and op2. A > macro could expand into all the same dispatching source that would go > into a function, but there is no point in that.
I thought that the macro could recognize whether the argument was a sequence or not... If I understood things well, a macro is expanded at compile time, so in my program when I call (my-macro 'list (+ '(1 2 3) 5)) why would the macro be unable to sort out the type of the arguments ? '(1 2 3) is a list, even at compile-time, is it not ?
> As for the GF's espen proposed only working where there are two > operands, check out REDUCE. But then you have the problem of generating > methods for each permutation:
> (my+ number sequence) > (my+ sequence number)
> ..etc. This is where you could use a macro to take one definition and > have it write the permutations.
Well, so I guess I understood wrong Paul Graham's sentence about macros being transformations... I'll just think about it, maybe I'll understand it some day (the day I'll be ready for macros ?)...
>>>> Martin Raspaud <martin.rasp...@wanadoo.fr> writes:
>>>>> I'm quite new to lisp, but I started writing a bit of code... Things >>>>> are getting on well (at least, it's working) but I didn't use any >>>>> macro yet... I'm reading Paul Graham's "On Lisp" which I find great, >>>>> but I'm still not very at ease with macros.
>>>> Hmm, are you sure you're ready for "On Lisp" yet? Most lisp programmers >>>> (myself included) dive into macros a little to early.
>>> Yep maybe, but better soon than never ;-)
>> Well, I think the point was not never to use them, but not to dive in >> to macros just for the sake of using macros. But I like your >> damn-the-torpedos attitude, so...
>> Methinks one problem is that the macro will only see the source, and I >> wager you would like to use more than literals with your little hack. >> So something like:
>> ...well, needs more than luck, it needs run-time dispatch (in some >> form or other) based on the types of the objects bound to op1 and op2. >> A macro could expand into all the same dispatching source that would >> go into a function, but there is no point in that.
> I thought that the macro could recognize whether the argument was a > sequence or not... If I understood things well, a macro is expanded at > compile time, so in my program when I call (my-macro 'list (+ '(1 2 3) > 5)) why would the macro be unable to sort out the type of the arguments > ? '(1 2 3) is a list, even at compile-time, is it not ?
Yes, but you dashed through what I wrote too quickly. It is fine for you to tackle macros too soon since that only wastes your time. Now you are wasting mine. Bad, newbie! Bad! :)
Look at the example I gave and tell me what type you think the macro good-luck will see at compile-time.
Here's another problem of which I did not think:
(defmacro macriddle-1 (arg) (format t "~&yes I am a ~a, but why is my length ~a, not ~a?" (type-of arg) (length arg) (length (second arg))))
(macriddle-1 '(1 2 3))
=> yes I am a CONS, but why is my length 2, not 3?
Martin Raspaud <martin.rasp...@wanadoo.fr> writes: > Well, so I guess I understood wrong Paul Graham's sentence about > macros being transformations... I'll just think about it, maybe I'll > understand it some day (the day I'll be ready for macros ?)...
You might be interested in taking a look at the chapter about macros from my book in progress:
They approach things a bit differently than Graham; maybe a new perspective will help. If you read them and have any comments for me I'd love to hear them. Other chapters ready for feedback are available at:
> Martin Raspaud <martin.rasp...@wanadoo.fr> writes:
>>Well, so I guess I understood wrong Paul Graham's sentence about >>macros being transformations...
I forgot to mention....
You dishonor macros twice, first by setting them on too high a pedestal, then in your disappointment setting them too low. (IP violation of Stendhal's chapter on "infatuation", in "On Love".)
Macros do /not/ see run-time types, they /do/ transform code.
Martin Raspaud <martin.rasp...@wanadoo.fr> writes: > Hi all,
> I'm quite new to lisp, but I started writing a bit of code... Things > are getting on well (at least, it's working) but I didn't use any > macro yet... I'm reading Paul Graham's "On Lisp" which I find great, > but I'm still not very at ease with macros. He writes that macros are > made to transform expressions... So I thought "let's write a small > macro for my needs" : I would like to extend classic arithmetic > operations to sequences... for example > (my-macro 'list (+ '(1 2 3) #(3 2 1))) would return (4 4 4), but also > (my-macro 'vector (+ '(1 2 3) 5)) would return #(6 7 8) and > (my-macro 'list (+ '(1 2 3) (* 5 '(1 2 3)))) would return (6 12 18)
> so, take Paul Graham's method, I would write what I'll have to type : > * (my-macro 'list (+ number1 sequence2 (* sequence3 number4)))
> but honestly I really don't know how to write the macro after > that... The most mysterious part for me is how to transform the > sequences in the original expression into variables for the lambda > function...
> Could anyone enlighten me ?
It has not been pointed out that you can always quote the whole expression to have it processed at run time by a function:
Now, what would be important in your case is to specify comprehensively the sematics and the syntax you want for these expressions.
For example:
expression ::= sum | product | substraction | division . sum ::= (+ term ... ) product ::= (* term ... ) substraction ::= (- term term ... ) division ::= (/ term term ... ) term ::= expression | scalar_term | vector_term | list_term scalar_term ::= number ;; a lisp _number_. vector_term ::= vector ;; a lisp _vector_ of numbers. list_term ::= list ;; a lisp _list_ of numbers.
That is, you don't need to quote the lists of number inside the expression because you can distinguish them from expression by their car being a number instead of being an operator.
Did I forgot variables? You'd have to specify it!
Then you have to specify the sematics and semantic constraints of your expressions:
(+ seq1 ... seqn) --> (seq (+ (elt seq1 0) ... (elt seqn 0)) (+ (elt seq1 1) ... (elt seqn 1)) ... (+ (elt seq1 p) ... (elt seqn p))) ;; seq is either vector or list depending on what result is expected. ;; seqi can be either a vector or a list. ;; what happens when (/= (length seqi) (length seqj)) ?
That may seem obvious, but writting out these specifications you'll see that you'll discover questions that need to be answered, and at the same time you'll have defined an abstract implementation: you'll see better what you need to implement and therefore how to do it.
_Finally_, you'll be able to make a choice about whether you need a macro or a function to implement this.
Note that if you want to be able to use variable in your expressions, you could do either:
-- __Pascal_Bourguignon__ http://www.informatimago.com/ There is no worse tyranny than to force a man to pay for what he doesn't want merely because you think it would be good for him.--Robert Heinlein http://www.theadvocates.org/
>>>> Martin Raspaud <martin.rasp...@wanadoo.fr> writes:
>>>>> I'm quite new to lisp, but I started writing a bit of code... Things >>>>> are getting on well (at least, it's working) but I didn't use any >>>>> macro yet... I'm reading Paul Graham's "On Lisp" which I find great, >>>>> but I'm still not very at ease with macros.
>>>> Hmm, are you sure you're ready for "On Lisp" yet? Most lisp programmers >>>> (myself included) dive into macros a little to early.
>>> Yep maybe, but better soon than never ;-)
>> Well, I think the point was not never to use them, but not to dive in >> to macros just for the sake of using macros. But I like your >> damn-the-torpedos attitude, so...
>> Methinks one problem is that the macro will only see the source, and I >> wager you would like to use more than literals with your little hack. >> So something like:
>> ...well, needs more than luck, it needs run-time dispatch (in some >> form or other) based on the types of the objects bound to op1 and op2. >> A macro could expand into all the same dispatching source that would >> go into a function, but there is no point in that.
> I thought that the macro could recognize whether the argument was a > sequence or not... If I understood things well, a macro is expanded at > compile time, so in my program when I call (my-macro 'list (+ '(1 2 3) > 5)) why would the macro be unable to sort out the type of the arguments > ? '(1 2 3) is a list, even at compile-time, is it not ?
If that's all you're doing, fine. But it's more likely that you'll be calling (eventually if not now) (my-macro 'list (+ foo bar)) where foo and bar get passed in from an entirely different place. Or (my-macro 'list (op-to-do foo bar)). And then you need a little more. If you're just operating on literals known at compile time, you barely need a macro.
Martin Raspaud <martin.rasp...@wanadoo.fr> writes: > Martin Raspaud wrote : >> Hi all, >> [bla bla bla] >> Martin
> Thanks all, I think I got the point (more or less). Anyway, sorry for > wasting your time ;-)
I think you were attempting something too ambitious for a simple macro. (and I think that extending generic arithmetic to encompass sequences is probably not something for a macro anyway).