> Programming Languages > Lisp
Various Topics Home | Disclaimer | Report Adult Posts

Various Topics on Lisp



Lisp - "Sharp-colon reader macro" in Programming Languages


Old 09-21-2004   #11
..ss.. ..kol..
 
Default Re: Sharp-colon reader macro

Alan Crowe <alan@cawtech.freeserve.co.uk> writes:

> [...]
> lexical scoping saves me with distinct, nested bindings of the same
> symbol.



Not always.

Consider the following (simplistic) example of providing read-only
access to the iteration counter:

(defmacro repeat ((counter-reader-name count-form) &body body)
(let ((counter-var (gensym)))
`(macrolet ((,counter-reader-name () '(identity ,counter-var)))
(dotimes (,counter-var ,count-form) ,@body))))

and the following use:

(repeat (i 2) (repeat (j 2) (format t "~%~D ~D" (i) (j))))

and then the result from replacing the call to GENSYM with
'#:COUNTER.


---V***il.


--
V***il Nikolov <vnikolov@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
 
Old 09-21-2004   #12
.... ..o..
 
Default Re: Sharp-colon reader macro

Pascal Bourguignon wrote:
> Now you should see when you can get problems: when you use the
> anonymous symbol for something else than a lexical variable. Anything
> that modifies a global state, be it the current package or for example
> a hash table where you store the anonymous symbol with some other
> data, for reference by other code generated by your macro.
>
> For example:
>
> (defmacro defcommand (pattern &body body)
> (let ((name #:command))
> `(progn
> (defun ,name (args) ,@body)
> (push (cons ',pattern ',name) *commands*))))
>
> (defmacro parse-command (command)
> `(match-case ,command
> ,@(mapcar (lambda (p-f)
> `(,(car p-f) (,(cdr-pf) ,(collect-vars ,(car p-f)))))
> *commands*)))
>
> (defcommand (take (?x object))
> (detach object)
> (attach object (bag *player*)))
>
> (defcommand (throw (?x object))
> (cond ((containp (bag player) object)
> (detach object)
> (attach object *ground*))
> (t (error "You don't hold ~A" object))))
>
> (loop for command = (read) do
> (parse-command command))


Thankyou Pascal, that is a tremendous example. I'm
stunned. My own efforts to contrive a need for GENSYM rather
than Sharpsign Colon started with special variables
(excessive use of special variables is the royal road to
toxic symbol clashes, I think). Err, then I got stuck,
without a credible scenario.

I'm especially impressed because I had toyed with this kind
of adventure code quite recently. How should parse command
work? I was doing (apply (car command)(cdr command)). I
avoided clashes between my commands and functions in the
program by having a command package. The functions that
implemented the commands started

(defun command:take (&rest stuff) etc etc)

I was well pleased with this code, so to have your example
code show me, in p***ing, a better way has expanded my
horizons wonderfully. I've spent a few hours writing a
minimal pattern matcher and filling in the details so I can
play with running code and soak up the implications. Now I
know why GENSYM clutters up my macroexpansions with those
irritating numbers. When I look in *COMMANDS* I really want
to see:

(((HIT MONSTER WITH (X)) . #:HIT-971)
((DROP (X) ON MONSTER) . #ROP-970)
((THROW ROCK AT MONSTER) . #:THROW-969)
((THROW (X) AT (Y)) . #:THROW-968))

with numbers to tell me that the THROW symbols are distinct
and it is all working right.

Having powerful macros to type all the boilerplate for you
makes programming fun

* (let ((*readtable* (copy-readtable)))
(set-macro-character #\newline (get-macro-character #\) ))
(loop for command = (progn
(format t "~&> ")
(read-delimited-list #\newline))
do (parse-command command)))

> hit monster with sword

The monster snarls at you.
> drop anvil on monster

You got a step ladder to stand on?
> hit monster with rock

The monster snarls at you.
> throw rock at monster

The monster picks you up by the scruff of the neck
and drops you into the debugger!

Error in function "Top-Level Form": Broken fourth wall.

Restarts:
0: [CONTINUE] Return to the dungeon
1: [ABORT ] Return to Top-Level.


Alan Crowe
Edinburgh
Scotland
 

Thread Tools
Display Modes





Powered by vBulletin®
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0