Pragmatic Parsing in Common Lisp
Henry Baker
http://home.pipeline.com/~hbaker1/Prag-Parse.html
SERIES package for Common Lisp
Richard Waters
http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node347.html
@techreport{ siskind91screamer,
author = "Jeffrey Mark Siskind and David Allen McAllester",
title = "Screamer: {A} Portable Efficient Implementation of
Nondeterministic Common Lisp",
number = "IRCS-93-03",
address = "Philadelphia, PA",
year = "1991",
url = "citeseer.ist.psu.edu/siskind93screamer.html" }
Funny, but I seem to have argued this question before with Alex
Martelli.
http://mail.python.org/pipermail/python-list/2003-October/229805.html
I gave two examples of interesting macro expansion. One from series:
(defun example ()
(let ((elements '(3 -1 4 -1 5 -9 2 -6 5 -3)))
(/ (reduce #'max (map 'list #'abs elements))
(reduce #'+ elements))))
This works, but it is inefficient because MAP and the second REDUCE
both traverse the list, and the intermediate list generated by MAP is
immediately discarded (consumed) by the first REDUCE.
The series version appears quite similar:
(defun series-example ()
(let ((elements (scan '(3 -1 4 -1 5 -9 2 -6 5 -3))))
(/ (collect-max (#m abs elements))
(collect-sum elements))))
but if you macroexpand the body, you get this:
(COMMON-LISP:LET* (ELEMENTS (#:LISTPTR-702 '(3 -1 4 -1 5 -9 2 -6 5
-3)) #:ITEMS-710 (#:NUMBER-707 NIL) (#:SUM-714 0))
(DECLARE (TYPE LIST #:LISTPTR-702) (TYPE NUMBER #:SUM-714))
(TAGBODY
#:LL-717 (IF (ENDP #:LISTPTR-702) (GO SERIES::END))
(SETQ ELEMENTS (CAR #:LISTPTR-702))
(SETQ #:LISTPTR-702 (CDR #:LISTPTR-702))
(SETQ #:ITEMS-710 ((LAMBDA (#:V-708) (ABS #:V-708))
ELEMENTS))
(IF (OR (NULL #:NUMBER-707) (< #:NUMBER-707
#:ITEMS-710)) (SETQ #:NUMBER-707 #:ITEMS-710))
(SETQ #:SUM-714 (+ #:SUM-714 ELEMENTS))
(GO #:LL-717)
SERIES::END)
(IF (NULL #:NUMBER-707) (SETQ #:NUMBER-707 NIL))
(/ #:NUMBER-707 #:SUM-714))
This code avoids traversing the series more than once and does not
create an intermediate series just to discard it. It does this by
analyzing the code and determining that the computation may procede in
`lock step'.
This example is from Screamer:
(and seems relevant to a different thread on this list!)
(defun pythagorean-triples (n)
(all-values
(let ((a (an-integer-between 1 n))
(b (an-integer-between 1 n))
(c (an-integer-between 1 n)))
(unless (= (+ (* a a) (* b b)) (* c c)) (fail))
(list a b c))))
The body of this function expands into:
(LET ((VALUES 'NIL) (SCREAMER::LAST-VALUE-CONS NIL))
(LET ((SCREAMER::TRAIL-POINTER (FILL-POINTER SCREAMER::*TRAIL*)))
(SCREAMER::CHOICE-POINT-INTERNAL
(PROGN
(LET ((#:DUMMY-29301 N))
(LET ((#:CONTINUATION-29303
#'(LAMBDA (&OPTIONAL #:DUMMY-29283 &REST
#:OTHER-29284)
(DECLARE (SCREAMER::MAGIC) (IGNORE
#:OTHER-29284))
(PROGN
(LET ((#:DUMMY-29296 N))
(LET ((#:CONTINUATION-29298
#'(LAMBDA (&OPTIONAL #:DUMMY-29285
&REST #:OTHER-29286)
(DECLARE (SCREAMER::MAGIC)
(IGNORE #:OTHER-29286))
(PROGN
(LET ((#:DUMMY-29291 N))
(LET ((#:CONTINUATION-29293
#'(LAMBDA (&OPTIONAL
#:DUMMY-29287 &REST #:OTHER-29288)
(DECLARE
(SCREAMER::MAGIC) (IGNORE #:OTHER-29288))
(LET ((C
#:DUMMY-29287)
(B
#:DUMMY-29285)
(A
#:DUMMY-29283))
(PROGN
(IF (NULL (=
(+ (* A A) (* B B)) (* C C)))
(PROGN
(FAIL)))
(LET
((#:DUMMY-29281 (LIST A B C)))
(LET
((SCREAMER::VALUE #:DUMMY-29281))
(PROGN
(GLOBAL
(COND ((NULL VALUES)
(SETF
SCREAMER::LAST-VALUE-CONS
(LIST SCREAMER::VALUE))
(SETF
VALUES
SCREAMER::LAST-VALUE-CONS))
(T
(SETF
(REST SCREAMER::LAST-VALUE-CONS)
(LIST SCREAMER::VALUE))
(SETF
SCREAMER::LAST-VALUE-CONS
(REST
SCREAMER::LAST-VALUE-CONS)))))
(FAIL)))))))))
(DECLARE (DYNAMIC-EXTENT
#:CONTINUATION-29293))
(SCREAMER::AN-INTEGER-
BETWEEN-NONDETERMINISTIC #:CONTINUATION-29293
1
#:DUMMY-29291)))))))
(DECLARE (DYNAMIC-EXTENT
#:CONTINUATION-29298))
(SCREAMER::AN-INTEGER-BETWEEN-
NONDETERMINISTIC #:CONTINUATION-29298
1
#:DUMMY-29296)))))))
(DECLARE (DYNAMIC-EXTENT #:CONTINUATION-29303))
(SCREAMER::AN-INTEGER-BETWEEN-NONDETERMINISTIC
#:CONTINUATION-29303 1 #:DUMMY-29301))))))
VALUES)
sometimes the fun reading postings is proportional to the line width...
could you repost it without those added line breaks? Please.
Stupid Google news posting grumble grumble. I don't think I can
disable the extra line breaks. I copied a good chunk of my response
from
http://mail.python.org/pipermail/python-list/2003-October/229805.html
so you can get a lot of the text there with the correct line breaks.
Just out of curiosity, I downloaded series package after reading cltl2
but I didn't had a chance to play with it. What's your experiences?
thanks
bobi
It's a mixed bag. For the things it does well, it does a *very* nice
job. For some of the other things, it can be persuaded. For some
things it is simply the wrong tool. I was using it for a lot of file
processing and it was great to write things like this:
(defun utf-8->ucs-2 (utf8string)
"Convert a ustring to a lw:text-string."
(collect 'string
(#m code-char
(ucs-4->ucs-2
(utf-8->ucs-4
(scan 'simple-vector-8b
(code-unit-vector utf8string)))))))
But since series will only optimize those computations that can go in
lock-step, it was, shall we say, *interesting* to write utf-8->ucs-4
where we were consuming between 1 and 6 bytes per output.
This analogy is helpful:
in imperative lang, their people are often proud and wonder at the
power of their eval() function. For example, Perl, PHP, Python all
have eval(). I explain, in pratical ways, that lisp's inherent symbol
system,
basically makes the entire language a “eval” system. (see What is
Expressiveness in a Computer Language
http://xahlee.org/perl-python/what_is_expresiveness.html )
Sometimes few months ago, i was studying lisp macros, and realized a
similar analogy. One often hear Lisper wonder and marvel about lisp's
macro system, which gives the lisp touting right as a meta-programing
language. But in Mathematica, in practical sense, almost every line
of code functions as lisp's macro; the entire language is just one
giant macro system! It is not a wonder, that one line of Mathematica
is like 10 to 100 lines of Common Lisp. (not considering the
mathematical function in mathematica, like derivative, integral,
differential equation, transcendental (math) functions... etc. If we
consider these, then one line of mathematica is pratically like one
thousand lines of Common Lisp, Allah!)
I'm afraid that people like Harrop have made me jaded. Show me
something. Make my jaw drop.
> one line of mathematica is pratically like one thousand lines of Common Lisp
Your statement reminds me of "Master Foo and the Ten Thousand
Lines"[1] except that Master Foo knows what he's talking about.
Aziz,,,
[1] http://catb.org/~esr/writings/unix-koans/ten-thousand.html
> Subject: Macros for seriously interested people
Thanks Joe, there is some nice 'meat' in that post!
Tim
--
tcross (at) rapttech dot com dot au
> Joe Marshall <eval....@gmail.com> writes:
>
>> Subject: Macros for seriously interested people
>
> Thanks Joe, there is some nice 'meat' in that post!
I find Screamer in particular a really impressive piece of work.
Screamer is an impressive grab bag of techniques to embed an extension
into lisp (not that I have a deep understanding of the code). However,
it's not seamless. My frustrations in writing my own extensions come
from lacking the nuance to both hide the machinery, and stay in the
language at the same time (especially where flow control is involved).
Matt
--
"You do not really understand something unless you
can explain it to your grandmother." - Albert Einstein.
I'd noticed the Debian screamer package and had put it on my "Things to check
out" list. No, after Joe's post and looking at some of those links, I've just
started checking it out. I does look pretty impressive to me, but then again,
I'm still at the stage of being impressed on pretty much a weekly basis by
the way things are done in CL.
Typesetting macros convert mathematical notation into scene graphs that can
be rendered:
http://www.ffconsultancy.com/tmp/mathematica.png
--
Dr Jon D Harrop, Flying Frog Consultancy
The F#.NET Journal
http://www.ffconsultancy.com/products/fsharp_journal/?usenet
> Joe Marshall wrote:
>> ... Show me something ...
>
> Typesetting macros convert mathematical notation into scene graphs that can
> be rendered:
>
> http://www.ffconsultancy.com/tmp/mathematica.png
Bah.
http://www.fractalconcept.com/ex.pdf