Why don't people like lisp?
prunesquallor at comcast.net
prunesquallor at comcast.net
Thu Oct 23 19:14:56 EDT 2003
Marcin 'Qrczak' Kowalczyk <qrczak at knm.org.pl> writes:
> On Thu, 23 Oct 2003 12:11:30 -0400, Joe Marshall wrote:
>
>> So if we extended Lisp, for example, I could write:
>
>> (defun pythagorean-triples (n)
>> (all-values
>> (let ((opposite (an-integer-between 1 n))
>> (adjacent (an-integer-between 1 n))
>> (hypotenuse (an-integer-between 1 n)))
>> (if (= (+ (* opposite opposite)
>> (* adjacent adjacent))
>> (* hypotenuse hypotenuse))
>> (list opposite adjacent hypotenuse)
>> (fail)))))
>
> How to write such macros in Lisp? Looks like they would require non-local
> rewriting of program structure, I don't see how it's possible at all.
It ain't easy, but it is possible. (In Scheme it is a bit easier
because of first-class continuations, but that's a different issue.)
The key point here is that the authors (Jeffrey Mark Siskind and David
McAllester) of the macros didn't have to implement an entire
non-deterministic language, they merely had to extend the existing one
with a small well-designed set of macros. Things like garbage
collection, interrupts, unwind-protect, parsers, code-generators,
file-system i/o, etc. are time consuming and tricky. By extending
an existing known implementation, they finesse *all* that work.
Additionally, I don't have to learn an entire domain-specific language
to use their package. I learn a few extra macros and I'm done.
(pprint (macroexpand '(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)))))
=>
(LET* ((VALUES 'NIL) (LAST-VALUE-CONS NIL) (TRAIL-POINTER (FILL-POINTER *TRAIL*)))
(CATCH 'FAIL
(LET ((*NONDETERMINISTIC?* T))
(UNWIND-PROTECT
(PROGN
(LET* ((#:DUMMY-728 N)
(#:CONTINUATION-730
(LAMBDA (&OPTIONAL #:DUMMY-710 &REST #:OTHER-711)
(LET* ((#:DUMMY-723 N)
(#:CONTINUATION-725
(LAMBDA (&OPTIONAL #:DUMMY-712 &REST #:OTHER-713)
(LET* ((#:DUMMY-718 N)
(#:CONTINUATION-720
(LAMBDA (&OPTIONAL #:DUMMY-714 &REST #:OTHER-715)
(LET ((C #:DUMMY-714)
(B #:DUMMY-712)
(A #:DUMMY-710))
(IF (NULL (= (+ (* A A) (* B B)) (* C C)))
(FAIL))
(LET* ((#:DUMMY-708 (LIST A B C))
(VALUE #:DUMMY-708))
(GLOBAL
(COND ((NULL VALUES)
(SETF LAST-VALUE-CONS (LIST VALUE))
(SETF VALUES LAST-VALUE-CONS))
(T
(SETF
(REST LAST-VALUE-CONS)
(LIST VALUE))
(SETF
LAST-VALUE-CONS
(REST LAST-VALUE-CONS)))))
(FAIL))))))
(AN-INTEGER-BETWEEN-NONDETERMINISTIC
#:CONTINUATION-720
1
#:DUMMY-718)))))
(AN-INTEGER-BETWEEN-NONDETERMINISTIC
#:CONTINUATION-725
1
#:DUMMY-723)))))
(AN-INTEGER-BETWEEN-NONDETERMINISTIC #:CONTINUATION-730 1 #:DUMMY-728)))
(BLOCK NIL
(TAGBODY
LOOP (IF (= (FILL-POINTER *TRAIL*) TRAIL-POINTER) (RETURN))
(FUNCALL (VECTOR-POP *TRAIL*))
(SETF (AREF *TRAIL* (FILL-POINTER *TRAIL*)) NIL)
(GO LOOP))))))
VALUES)
More information about the Python-list
mailing list