* Evaluation of macro arguments @ 2016-01-05 10:59 Marcin Borkowski 2016-01-05 12:55 ` Stefan Monnier 2016-01-05 19:22 ` Pascal J. Bourguignon 0 siblings, 2 replies; 10+ messages in thread From: Marcin Borkowski @ 2016-01-05 10:59 UTC (permalink / raw) To: Help Gnu Emacs mailing list Hi all, continuing my quest to grok macro argument evaluation issues, I'd like (again) to make sure that I get it correctly. So I have this simple macro generating a list of consecutive numbers (which is not without problems - I am aware of those, namely (i) it uses hard-coded symbols instead of generating them on the fly, and (ii) it has no error checking): (defmacro range (from dir to) `(let ((delta (cond ((eq ',dir 'upto) 1) ((eq ',dir 'downto) -1))) (i ,from) (list nil)) (while (not (= i ,to)) (push i list) (setq i (+ i delta))) (nreverse list))) Do I get it correctly that if I want to write an Edebug spec for this macro, I should mark the second argument as _not evaluated_, because its value is actually quoted? (Also, do I get it right that the spec for the second argument should be e.g. `symbolp', or - if I want to have more error-checking while edebugging - I should _define_ a predicate like this (defun upto-or-downto-p (symbol) (memq symbol '(upto downto))) since the predicate in the edebug spec cannot be a lambda expression? TIA, -- Marcin Borkowski http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski Faculty of Mathematics and Computer Science Adam Mickiewicz University ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Evaluation of macro arguments 2016-01-05 10:59 Evaluation of macro arguments Marcin Borkowski @ 2016-01-05 12:55 ` Stefan Monnier 2016-01-13 22:16 ` Marcin Borkowski 2016-01-05 19:22 ` Pascal J. Bourguignon 1 sibling, 1 reply; 10+ messages in thread From: Stefan Monnier @ 2016-01-05 12:55 UTC (permalink / raw) To: help-gnu-emacs > Do I get it correctly that if I want to write an Edebug spec for this > macro, I should mark the second argument as _not evaluated_, because its > value is actually quoted? That's right. > (Also, do I get it right that the spec for the second argument should be > e.g. `symbolp', or - if I want to have more error-checking while > edebugging - I should _define_ a predicate like this > > (defun upto-or-downto-p (symbol) > (memq symbol '(upto downto))) > > since the predicate in the edebug spec cannot be a lambda expression? Something like it, yes (tho it's not really "checked while edebugging". Instead, such a precise Edebug spec would cause an error (and not a very pretty one) when you ask Edebug to annotate the code). I'd use a spec like (declare (debug (form symbolp form))). Stefan ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Evaluation of macro arguments 2016-01-05 12:55 ` Stefan Monnier @ 2016-01-13 22:16 ` Marcin Borkowski 2016-01-14 13:47 ` Stefan Monnier 0 siblings, 1 reply; 10+ messages in thread From: Marcin Borkowski @ 2016-01-13 22:16 UTC (permalink / raw) To: Stefan Monnier; +Cc: help-gnu-emacs On 2016-01-05, at 13:55, Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> Do I get it correctly that if I want to write an Edebug spec for this >> macro, I should mark the second argument as _not evaluated_, because its >> value is actually quoted? > > That's right. > >> (Also, do I get it right that the spec for the second argument should be >> e.g. `symbolp', or - if I want to have more error-checking while >> edebugging - I should _define_ a predicate like this >> >> (defun upto-or-downto-p (symbol) >> (memq symbol '(upto downto))) >> >> since the predicate in the edebug spec cannot be a lambda expression? > > Something like it, yes (tho it's not really "checked while edebugging". Hi, I finally sat down to this. I still don't get it. If it's not checked while edebugging, what's the point of the precise declaration? > Instead, such a precise Edebug spec would cause an error (and not > a very pretty one) when you ask Edebug to annotate the code). > I'd use a spec like (declare (debug (form symbolp form))). I tried it and did not get any error message. Why? More precisely, here's what I have done: --8<---------------cut here---------------start------------->8--- (defun upto-or-downto-p (symbol) (memq symbol '(upto downto))) (defmacro range (from dir to) "Return a list of numbers starting with FROM and going up to TO-1 if DIR is the symbol 'upto or down to TO+1 if DIR is the symbol 'downto. Warning: this version is broken!" (declare (debug (form upto-or-downto-p form))) `(let ((delta (cond ((eq ',dir 'upto) 1) ((eq ',dir 'downto) -1))) (i ,from) (list nil)) (while (not (= i ,to)) (push i list) (setq i (+ i delta))) (nreverse list))) (range (- 5 4) upto (+ 4 6)) --8<---------------cut here---------------end--------------->8--- Then I pressed C-u C-M-x on the last form, and everything went smoothly. If I replace 'upto with something else, I get this: edebug-syntax-error: Invalid read syntax: upto-or-downto-p, "failed" So basically it seems that I was (more or less) right. OTOH, I can't be right about anything Emacs-related and you be wrong on it, so what's going on? > Stefan Best, -- Marcin Borkowski http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski Faculty of Mathematics and Computer Science Adam Mickiewicz University ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Evaluation of macro arguments 2016-01-13 22:16 ` Marcin Borkowski @ 2016-01-14 13:47 ` Stefan Monnier 2016-01-14 20:32 ` Marcin Borkowski 0 siblings, 1 reply; 10+ messages in thread From: Stefan Monnier @ 2016-01-14 13:47 UTC (permalink / raw) To: Marcin Borkowski; +Cc: help-gnu-emacs > I still don't get it. If it's not checked while edebugging, what's the > point of the precise declaration? It's *used* (rather than checked) when *setting up* the Edebug instrumentation, rather than while single stepping through the code. [ I realize now that maybe "setup edebug instrumentation" is what you meant by "edebugging", while to me "edebugging" means something more like single-stepping, which is what happens after the instrumentation has been put in place. ] >> Instead, such a precise Edebug spec would cause an error (and not >> a very pretty one) when you ask Edebug to annotate the code). >> I'd use a spec like (declare (debug (form symbolp form))). > I tried it and did not get any error message. Why? More precisely, > here's what I have done: > --8<---------------cut here---------------start------------->8--- > (defun upto-or-downto-p (symbol) > (memq symbol '(upto downto))) > (defmacro range (from dir to) > "Return a list of numbers starting with FROM and going up to > TO-1 if DIR is the symbol 'upto or down to TO+1 if DIR is the > symbol 'downto. Warning: this version is broken!" > (declare (debug (form upto-or-downto-p form))) > `(let ((delta (cond ((eq ',dir 'upto) 1) > ((eq ',dir 'downto) -1))) > (i ,from) > (list nil)) > (while (not (= i ,to)) > (push i list) > (setq i (+ i delta))) > (nreverse list))) > (range (- 5 4) upto (+ 4 6)) > --8<---------------cut here---------------end--------------->8--- > Then I pressed C-u C-M-x on the last form, and everything went > smoothly. Yes, that's normal. > If I replace 'upto with something else, I get this: > edebug-syntax-error: Invalid read syntax: upto-or-downto-p, "failed" That's the error I was referring to (and indeed, if the code is right you should not be getting an error). The error can become more troublesome for more complex Edebug specs where Edebug can try various alternatives in which case the error you get may be about an alternative which shouldn't have been tried anyway. To see the difference between "instrumentation" and "single-stepping", you need to try C-u C-M-x on something like (defun my-foo () (range (- 5 4) typo (+ 4 6))) where you'll immediately get the error during C-u C-M-x rather than latr on when you call my-foo. > So basically it seems that I was (more or less) right. OTOH, I can't > be right about anything Emacs-related and you be wrong on it, so what's > going on? I think we were just in violent agreement. Stefan ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Evaluation of macro arguments 2016-01-14 13:47 ` Stefan Monnier @ 2016-01-14 20:32 ` Marcin Borkowski 2016-01-14 23:05 ` Stefan Monnier 0 siblings, 1 reply; 10+ messages in thread From: Marcin Borkowski @ 2016-01-14 20:32 UTC (permalink / raw) To: Stefan Monnier; +Cc: help-gnu-emacs On 2016-01-14, at 14:47, Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> I still don't get it. If it's not checked while edebugging, what's the >> point of the precise declaration? > > It's *used* (rather than checked) when *setting up* the Edebug > instrumentation, rather than while single stepping through the code. > [ I realize now that maybe "setup edebug instrumentation" is what you > meant by "edebugging", while to me "edebugging" means something more > like single-stepping, which is what happens after the instrumentation > has been put in place. ] Well, it turns out that I was quite confused. Now that you wrote it, it does make perfect sense; in my experiments with this issue I instrumented single forms to be evaluated and not defuns, so (as you wrote below) there was no observable difference (both steps happened basically instantaneously). >>> Instead, such a precise Edebug spec would cause an error (and not >>> a very pretty one) when you ask Edebug to annotate the code). >>> I'd use a spec like (declare (debug (form symbolp form))). >> I tried it and did not get any error message. Why? More precisely, >> here's what I have done: > >> --8<---------------cut here---------------start------------->8--- >> (defun upto-or-downto-p (symbol) >> (memq symbol '(upto downto))) > >> (defmacro range (from dir to) >> "Return a list of numbers starting with FROM and going up to >> TO-1 if DIR is the symbol 'upto or down to TO+1 if DIR is the >> symbol 'downto. Warning: this version is broken!" >> (declare (debug (form upto-or-downto-p form))) >> `(let ((delta (cond ((eq ',dir 'upto) 1) >> ((eq ',dir 'downto) -1))) >> (i ,from) >> (list nil)) >> (while (not (= i ,to)) >> (push i list) >> (setq i (+ i delta))) >> (nreverse list))) > >> (range (- 5 4) upto (+ 4 6)) >> --8<---------------cut here---------------end--------------->8--- > >> Then I pressed C-u C-M-x on the last form, and everything went >> smoothly. > > Yes, that's normal. I would hope so! ;-) >> If I replace 'upto with something else, I get this: >> edebug-syntax-error: Invalid read syntax: upto-or-downto-p, "failed" > > That's the error I was referring to (and indeed, if the code is right > you should not be getting an error). The error can become more > troublesome for more complex Edebug specs where Edebug can try various > alternatives in which case the error you get may be about an alternative > which shouldn't have been tried anyway. Ah, so it has something to do with those &or, &and etc.? I have to admit that I did not really understand that part of the manual. I will try to understand it some day (sooner than later, I hope). It would be great if I managed to come up with a patch for the manual then to make it easier for future generations. ;-) Are there any worthy examples of edebug specs in Emacs sources? (I could just grep for them - and I'll probably do that anyway - but if somebody could point me to some of those which are especially suitable for understanding the thing, it would be great. Of course, I will start with the examples provided in the manual.) > To see the difference between "instrumentation" and "single-stepping", > you need to try C-u C-M-x on something like > > (defun my-foo () (range (- 5 4) typo (+ 4 6))) > > where you'll immediately get the error during C-u C-M-x rather than latr > on when you call my-foo. Makes sense, especially that (in my macro) the upto/downto has to sit right there in the code (I mean, literally - it cannot be the result of any evaluation, since that argument of my macro is never evaluated!) >> So basically it seems that I was (more or less) right. OTOH, I can't >> be right about anything Emacs-related and you be wrong on it, so what's >> going on? > > I think we were just in violent agreement. ;-) > Stefan Thanks for your patience! I'm slowly learning this stuff, and I hope to "pay back" to the community by at least writing a blog post, and maybe a patch for the manual. Best, -- Marcin Borkowski http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski Faculty of Mathematics and Computer Science Adam Mickiewicz University ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Evaluation of macro arguments 2016-01-14 20:32 ` Marcin Borkowski @ 2016-01-14 23:05 ` Stefan Monnier 0 siblings, 0 replies; 10+ messages in thread From: Stefan Monnier @ 2016-01-14 23:05 UTC (permalink / raw) To: Marcin Borkowski; +Cc: help-gnu-emacs > Ah, so it has something to do with those &or, &and etc.? Right. > Are there any worthy examples of edebug specs in Emacs sources? As a general rule of thumb, the more complex the macro, the more complex the debug spec. So you can take a look at the specs for cl-loop or pcase if you want "interesting" examples. Stefan ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Evaluation of macro arguments 2016-01-05 10:59 Evaluation of macro arguments Marcin Borkowski 2016-01-05 12:55 ` Stefan Monnier @ 2016-01-05 19:22 ` Pascal J. Bourguignon 2016-01-05 19:39 ` Marcin Borkowski 1 sibling, 1 reply; 10+ messages in thread From: Pascal J. Bourguignon @ 2016-01-05 19:22 UTC (permalink / raw) To: help-gnu-emacs Marcin Borkowski <mbork@mbork.pl> writes: > Hi all, > > continuing my quest to grok macro argument evaluation issues, I'd like > (again) to make sure that I get it correctly. So I have this simple > macro generating a list of consecutive numbers (which is not without > problems - I am aware of those, namely (i) it uses hard-coded symbols > instead of generating them on the fly, and (ii) it has no error > checking): > > (defmacro range (from dir to) > `(let ((delta (cond ((eq ',dir 'upto) 1) > ((eq ',dir 'downto) -1))) > (i ,from) > (list nil)) > (while (not (= i ,to)) > (push i list) > (setq i (+ i delta))) > (nreverse list))) (let ((i 0)) (list (range i 'upto (incf i 10)) ; bam! i)) I hope you may debug it well. -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Evaluation of macro arguments 2016-01-05 19:22 ` Pascal J. Bourguignon @ 2016-01-05 19:39 ` Marcin Borkowski 2016-01-05 20:30 ` Marcin Borkowski [not found] ` <mailman.1794.1452025850.843.help-gnu-emacs@gnu.org> 0 siblings, 2 replies; 10+ messages in thread From: Marcin Borkowski @ 2016-01-05 19:39 UTC (permalink / raw) To: Pascal J. Bourguignon; +Cc: help-gnu-emacs On 2016-01-05, at 20:22, Pascal J. Bourguignon <pjb@informatimago.com> wrote: > Marcin Borkowski <mbork@mbork.pl> writes: > >> Hi all, >> >> continuing my quest to grok macro argument evaluation issues, I'd like >> (again) to make sure that I get it correctly. So I have this simple >> macro generating a list of consecutive numbers (which is not without >> problems - I am aware of those, namely (i) it uses hard-coded symbols >> instead of generating them on the fly, and (ii) it has no error >> checking): >> >> (defmacro range (from dir to) >> `(let ((delta (cond ((eq ',dir 'upto) 1) >> ((eq ',dir 'downto) -1))) >> (i ,from) >> (list nil)) >> (while (not (= i ,to)) >> (push i list) >> (setq i (+ i delta))) >> (nreverse list))) > > (let ((i 0)) > (list (range i 'upto (incf i 10)) ; bam! > i)) > > I hope you may debug it well. That's unfair, Pascal; I wrote that I'm aware of this, I know how to make it work, and wasn't asking about it. Best, -- Marcin Borkowski http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski Faculty of Mathematics and Computer Science Adam Mickiewicz University ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Evaluation of macro arguments 2016-01-05 19:39 ` Marcin Borkowski @ 2016-01-05 20:30 ` Marcin Borkowski [not found] ` <mailman.1794.1452025850.843.help-gnu-emacs@gnu.org> 1 sibling, 0 replies; 10+ messages in thread From: Marcin Borkowski @ 2016-01-05 20:30 UTC (permalink / raw) To: Pascal J. Bourguignon; +Cc: help-gnu-emacs On 2016-01-05, at 20:39, Marcin Borkowski <mbork@mbork.pl> wrote: > On 2016-01-05, at 20:22, Pascal J. Bourguignon <pjb@informatimago.com> wrote: > >> Marcin Borkowski <mbork@mbork.pl> writes: >> >>> Hi all, >>> >>> continuing my quest to grok macro argument evaluation issues, I'd like >>> (again) to make sure that I get it correctly. So I have this simple >>> macro generating a list of consecutive numbers (which is not without >>> problems - I am aware of those, namely (i) it uses hard-coded symbols >>> instead of generating them on the fly, and (ii) it has no error >>> checking): >>> >>> (defmacro range (from dir to) >>> `(let ((delta (cond ((eq ',dir 'upto) 1) >>> ((eq ',dir 'downto) -1))) >>> (i ,from) >>> (list nil)) >>> (while (not (= i ,to)) >>> (push i list) >>> (setq i (+ i delta))) >>> (nreverse list))) >> >> (let ((i 0)) >> (list (range i 'upto (incf i 10)) ; bam! >> i)) >> >> I hope you may debug it well. > > That's unfair, Pascal; I wrote that I'm aware of this, I know how to > make it work, and wasn't asking about it. OK, technically you win, since I didn't notice that I evaluated `to' multiple times. Still, this was not what I was asking about - though thank you for pointing that out to me. It would be rather embarassing if I missed it. Best, -- Marcin Borkowski http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski Faculty of Mathematics and Computer Science Adam Mickiewicz University ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <mailman.1794.1452025850.843.help-gnu-emacs@gnu.org>]
* Re: Evaluation of macro arguments [not found] ` <mailman.1794.1452025850.843.help-gnu-emacs@gnu.org> @ 2016-01-08 23:13 ` duthen.mac.01 0 siblings, 0 replies; 10+ messages in thread From: duthen.mac.01 @ 2016-01-08 23:13 UTC (permalink / raw) To: help-gnu-emacs Hello! Le mardi 5 janvier 2016 21:30:52 UTC+1, Marcin Borkowski a écrit : > On 2016-01-05, at 20:39, Marcin Borkowski wrote: > > > On 2016-01-05, at 20:22, Pascal J. Bourguignon wrote: > >> > >> (let ((i 0)) > >> (list (range i 'upto (incf i 10)) ; bam! > >> i)) > >> > >> I hope you may debug it well. > OK, technically you win, since I didn't notice that I evaluated `to' > multiple times. Still, this was not what I was asking about - though > thank you for pointing that out to me. It would be rather embarassing > if I missed it. If you plan to use a variable "dir" with a "dynamic" value like this, (range a (if some-test 'upto 'downto) b) you have to "evaluate" "dir" at run time. But if you want to restrict it to a "lexical" symbol, you can do something like this: (defmacro range (from dir to) (declare (debug (form symbolp form)) (indent 3)) (let ((delta (cond ((eq dir 'upto) 1) ((eq dir 'downto) -1) (t (error "wrong dir: %s" dir))))) `(let ((i ,from) (to ,to) (list (list))) (while (not (= i to)) (push i list) (setq i (+ i ,delta))) (nreverse list)))) (defun test () (let ((i 0)) (list (range i upto (incf i 10)) i))) (test) -> ((0 1 2 3 4 5 6 7 8 9) 10) Note that "dir" is checked at expansion time and may generate an error. I have just a couple of remarks concerning macros: * if some variable is to be used more than once inside the body macro, it should be better to link it to a local variable (like "to" and "from" here), as already seen. * if the body of the macro does not embed any user code, you don't need to be afraid of variable conflict. You don't need to generate local variables. * you must respect the order of argument "evaluation". For example, this couple of macros seem ok, but... (defmacro range-up (from to) (declare (debug (form form)) (indent 2)) `(let ((i ,from) (to ,to) (list (list))) (while (not (> i to)) (push i list) (incf i)) (nreverse list))) (defmacro range-down (from to) (declare (debug (form form)) (indent 2)) `(nreverse (range-up ,to ,from))) ELISP> (range-up 3 7) (3 4 5 6 7) ELISP> (range-down 7 3) (7 6 5 4 3) ELISP> (let ((i 7)) (range-down i (decf i 4))) (3) HTH jack ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2016-01-14 23:05 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-01-05 10:59 Evaluation of macro arguments Marcin Borkowski 2016-01-05 12:55 ` Stefan Monnier 2016-01-13 22:16 ` Marcin Borkowski 2016-01-14 13:47 ` Stefan Monnier 2016-01-14 20:32 ` Marcin Borkowski 2016-01-14 23:05 ` Stefan Monnier 2016-01-05 19:22 ` Pascal J. Bourguignon 2016-01-05 19:39 ` Marcin Borkowski 2016-01-05 20:30 ` Marcin Borkowski [not found] ` <mailman.1794.1452025850.843.help-gnu-emacs@gnu.org> 2016-01-08 23:13 ` duthen.mac.01
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).