Few questions ...

Started by Kazimir Majorinc, October 11, 2009, 02:10:32 AM

Previous topic - Next topic

Jeff

#15
Lutz, one other thing. Shouldn't this be reader-event, not read-event?


(define (resume)
  (read-event rewrite))


Neither is documented in the manual.
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

Lutz

#16
I corrected the typo here: http://www.newlisp.org/macros/macro.lsp.html">http://www.newlisp.org/macros/macro.lsp.html



'reader-event' is part of the upcoming v.10.1.6. Here is the manual entry for it:



http://www.newlisp.org/downloads/development/newlisp_manual.html#reader-event">http://www.newlisp.org/downloads/develo ... ader-event">http://www.newlisp.org/downloads/development/newlisp_manual.html#reader-event



The "macro.lsp" is just one way to use 'reader-event'. Already the 'macro' function in macro.lsp isn't limited to transform defined functions. In (macro <pattern> <replacement>) any pattern could be there, it doesn't have to be a function call. Currently it is limited to a parenthesized expression, but you are free to change that ... and it doesn't have to be called 'macro' either, but made sence for what it currently does. It could be called 'compile' and write out a C program ;-)



'reader-event' just passes all top-level expressions and you 'reader-event' -handler can do any transformation on it you want.



Please nobody take the definition of 'macro' in macro.lsp as cast in stone, its just source which can be changed. The only fixed thing is the new built-in 'reader-event' function.



But these are the general rules you should follow when using 'reader-event':



1) Create a function, which somehow registers the patterns you want to translate and somehow tells what should be done with those patterns.



2) Create a transforming function (the reader-event handler) which searches each incoming expression for occurrence of this pattern and then does changes according do what has been prescribed.



3) Your event handler returns the new transformed expression to newLISP.

Jeff

#17
Thank you, Lutz. This is exactly the hook we need to extend the language. This is a good thing for the language.



Will reader-event be hooked into run-time compilation as well? That is, when I call read-expr, will the expression be first run through reader-event? I believe it should, so that translations that occur in one place happen everywhere. At the very least, it should be default. If it does not, it creates an inconsistency that must be accounted for in every program using read-expr and reader-event. It adds a workaround that must be memorized by new users, too.



It should not need to be hooked into load. Anything written to file should be in the expanded form in any case (at least, any code expressions written to file).
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

Lutz

#18
QuoteWill reader-event be hooked into run-time compilation as well? That is, when I call read-expr, will the expression be first run through reader-event?


Yes, 'eval-string', 'read-expr' and 'load' or in other words everything in the system translating source code will pass it through 'reader-event'. That is the default. If 'reader-event' is specified it fundamentally changes and extends your language.



But you can suspend 'reader-event' at any moment doing (reader-event nil). Should probably add this to the documentation.



Of course there are also dangers to this, but that is nothing new. If in the past you redefined built-in functions before doing a 'load' or 'eval-string' you could shoot yourself in the foot as well, or you can use it to your advantage: see the profiling module somebody wrote redefining 'define'.



Using 'reader-event' you coud write a profiler, which is a little more sane by not redefining 'define' but injecting timer/counter code into the 'defined' function without touching 'define' itself.

Jeff

#19
In fact, I think *I* may have written that :)
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

newdep

#20
Intresting!...

Even more stuff to study on ;-)
-- (define? (Cornflakes))

xytroxon

#21
Thankfully, newLISP is NOT Common LISP ;p)



I think a clean macro module function that doesn't require an advanced CS degree to fathom how it mysteriously works is a definite plus for newLISP... The fact that its name would confuse LISPers is devilshly clever and delightful!



But again, what better name?



Google Search: macro



Macro - Wikipedia, the free encyclopedia

Look up macro or macro- in Wiktionary, the free dictionary. Macro is commonly known as the prefix in the word macorana, but may also be used in: ...

en.wikipedia.org/wiki/Macro - Cached - Similar



Google Search: macorana



Did you mean: macarena  Top 2 results shown



Macarena (song) - Wikipedia, the free encyclopedia

Macarena is a Spanish song by Los del Río and Fangoria about a woman of the same name, or any woman from the La Macarena neighborhood of Seville, Spain. ...

Origin and history - Record breaking and worldwide ... - Music video

en.wikipedia.org/wiki/Macarena_(song) - Cached - Similar



Hum... macro... macarena... I think I got it!



Hey! macro-rena !



Where "rena" expands to reader event mnemonic algorithm



-- xytroxon



P.S. Can anyone play the macro-rena on their "mnemonica" for the shell game video audio? Ole!!!
\"Many computers can print only capital letters, so we shall not use lowercase letters.\"

-- Let\'s Talk Lisp (c) 1976

TedWalther

#22
How about a macro like this?


(macro function-to-detect-pattern function-to-transform-pattern character-stream)

Lutz, I understand you don't feel comfortable with people programming newLISP using the syntax of other languages.  But the whole point of reader macros is that that syntax gets mapped onto newLISP syntax.



Take, for instance, the tk function.  I'd like to mingle newLISP and tcl/tk calls at a deeper level than simply passing strings in various formats.



With read macros, quote and quasiquote and splice are easily implemented.



As with your current implementation of macro, reader macros will allow expansion to be done once as the expressions are read in, rather than being evaluated to generate new code every time, as is done with fexprs.



With a simple function pointer to the reader/parser, it can be arranged that there is NO performance slow-down when reader macros aren't enabled.



Ted


Quote from: "Lutz"I corrected the typo here: http://www.newlisp.org/macros/macro.lsp.html">http://www.newlisp.org/macros/macro.lsp.html



'reader-event' is part of the upcoming v.10.1.6. Here is the manual entry for it:



http://www.newlisp.org/downloads/development/newlisp_manual.html#reader-event">http://www.newlisp.org/downloads/develo ... ader-event">http://www.newlisp.org/downloads/development/newlisp_manual.html#reader-event



The "macro.lsp" is just one way to use 'reader-event'. Already the 'macro' function in macro.lsp isn't limited to transform defined functions. In (macro <pattern> <replacement>) any pattern could be there, it doesn't have to be a function call. Currently it is limited to a parenthesized expression, but you are free to change that ... and it doesn't have to be called 'macro' either, but made sence for what it currently does. It could be called 'compile' and write out a C program ;-)



'reader-event' just passes all top-level expressions and you 'reader-event' -handler can do any transformation on it you want.



Please nobody take the definition of 'macro' in macro.lsp as cast in stone, its just source which can be changed. The only fixed thing is the new built-in 'reader-event' function.



But these are the general rules you should follow when using 'reader-event':



1) Create a function, which somehow registers the patterns you want to translate and somehow tells what should be done with those patterns.



2) Create a transforming function (the reader-event handler) which searches each incoming expression for occurrence of this pattern and then does changes according do what has been prescribed.



3) Your event handler returns the new transformed expression to newLISP.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

m i c h a e l

#23
The new reader-event and macro module are muy bueno, Lutz. Thank you, once again, for all your hard work making newLISP such a fantastic programming language!



Unfortunately, it looks like we can't use the benefits of the new macro with dynamic dispatch:


newLISP v.10.1.6 on OSX IPv4 UTF-8, execute 'newlisp -h' for more info.

> (module "macro.lsp")
MAIN
> (new Class 'Pair)
Pair
> (define (Pair:left p) (p 1))
(lambda (p) (p 1))
> (macro (Pair:right P) (P 2))
(lambda-macro (P) (expand '(P 2)))
> (set 'p (Pair "A" 99))
(Pair "A" 99)
> (time (:left p) 1000000)
1081.388
> (time (:right p) 1000000)
1876.25
> _


Yikes! It takes almost twice as long!



On the other hand, if we fully qualify the method, like so:


> (time (Pair:left p) 1000000)
481.917
> (time (Pair:right p) 1000000)
54.432
> _


. . . we get the expected speed increases with the blazing speed of the new macro version.



Too bad, really. Accessors are a perfect candidate for these new C-like macros.



m i c h a e l

Lutz

#24
Yes, because the macro facility looks for the exact pattern in the source code when specifying:


(macro (Pair:right P) (P 2))

it will try to match (Pair:right *) not for (:right *)



On the other hand we cannot say:


(macro (:right P) (P 2)) ; causes an error


Because the way the 'macro:macro' function in macro.lsp currently is defined, it looks for the first symbol in the left expression to be undefined, to avoid double definitions. Remember that (:right P) really is (: right P) and it will take the ':' as the functor and not care about the 'right'.



Even if we redefine the functions 'macro:marco' and 'macro:rewrite' in a more general way to take translate this kind of expressions, it still wouldn't work. Because the ':' colon operator extracts the correct class of the object only during run-time. When translating the code (:right p), there is no way to find out, that the class is 'Pair' without evaluating 'p'.