Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

prog@

20 views
Skip to first unread message

Pascal Costanza

unread,
Nov 14, 2002, 10:50:15 AM11/14/02
to
Hi folks,

I have written the following macro.

(defun trans@ (list varsym)
(cond
((consp list)
(if (eq (car list) '@)
`((progn
(setf ,varsym
(multiple-value-list
,(trans@ (cadr list) varsym)))
(values-list ,varsym))
,@(trans@ (cddr list) varsym))
`(,(trans@ (car list) varsym)
,@(trans@ (cdr list) varsym))))
(t list)))

(defmacro prog@ (&body body)
(let ((result (gensym)))
`(let ((,result nil))
,@(trans@ body result)
(values-list ,result))))

Its purpose is to allow returning values from somewhere in the middle of
a function.

So for example you can do the following things.

> (prog@
(format t @"Hello, World!"))
Hello, World!
"Hello, World!"

(defmethod test ()
(format t "Hello, World!"))

(defmethod test :around ()
(format t "around: ")
@(call-next-method)
(format t " :around"))

> (test)
around: Hello, World! :around
NIL

The purpose of this posting is to check whether I have got this macro
right. It seems to work well - but is there anything I might have
overlooked? Any comments?


Thanks in advance,
Pascal

--
Pascal Costanza University of Bonn
mailto:cost...@web.de Institute of Computer Science III
http://www.pascalcostanza.de Römerstr. 164, D-53117 Bonn (Germany)

Nils Goesche

unread,
Nov 14, 2002, 11:35:17 AM11/14/02
to
Pascal Costanza <cost...@web.de> writes:

> I have written the following macro.

[snip]

> Its purpose is to allow returning values from somewhere in the
> middle of a function.
>
> So for example you can do the following things.
>
> > (prog@
> (format t @"Hello, World!"))
> Hello, World!
> "Hello, World!"
>
> (defmethod test ()
> (format t "Hello, World!"))
>
> (defmethod test :around ()
> (format t "around: ")
> @(call-next-method)
> (format t " :around"))
>
> > (test)
> around: Hello, World! :around
> NIL
>
> The purpose of this posting is to check whether I have got this
> macro right. It seems to work well - but is there anything I might
> have overlooked? Any comments?

What I don't like about it:

(prog@ 3 @2 (+ 2 3))

gives an error, and

(prog@ 32 @(+ 2 3) (print '(foo @ bar)))

doesn't print (FOO @ BAR) as it (IMHO) should. And the following
doesn't work, either:

(prog@ (flet ((foo (x)
(prog@
(print 'foo)
@(+ x 2)
(print 'foo-out))))
(format t "(FOO 40) is ~D" (foo 40)))
@(+ 5 7)
18)

Regards,
--
Nils Gösche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0

Kenny Tilton

unread,
Nov 14, 2002, 12:00:47 PM11/14/02
to

Pascal Costanza wrote:
> Hi folks,
>
> I have written the following macro.
>


...snip...


>
> Its purpose is to allow returning values from somewhere in the middle of
> a function.

Well, prog1 was my first thought, but then I see you aspire to:

(defun rodney ()
(yada-yada 4 5 6)
(+ 1 @(the-calculation-rodney-returns 2) 3)
(and-so-on 'a 'b 'c))

So my second thought is, how does the value meant to be returned by a
function get so little respect within said function?

prog1 does not bother me because yer kinda doing GF-ian :after processing:

(defun rodney (thing)
(yada-yada 4 5 6)
(prog1
(the-calculation-rodney-returns thing)
(mop-up-destructively thing)))

But in the first example the form whose value you
want to return is buried within some /other/ interesting form,
too far from the toplevel of the function to be progn'ed out.
So there is all this other stuff going on and the function's return
value (which strikes me as something pretty important to a function) is
just some form you happened to get to while doing /surrounding/ stuff
involving that form. Words fail me. it's like having a bit actor in a
stage play come out last to take a bow.

Lawdy, how often does this come up? I'd forget prog@ and think about
refactoring. Mind you, I am way out on a limb here because I do not
know what you are up to over there.

--

kenny tilton
clinisys, inc
---------------------------------------------------------------
""Well, I've wrestled with reality for thirty-five years, Doctor,
and I'm happy to state I finally won out over it.""
Elwood P. Dowd

Pascal Costanza

unread,
Nov 14, 2002, 12:44:59 PM11/14/02
to
Kenny Tilton wrote:

> Lawdy, how often does this come up? I'd forget prog@ and think about
> refactoring. Mind you, I am way out on a limb here because I do not
> know what you are up to over there.

Thanks for your comments. Well, I have seen the following idiom.

(defmethod m :around (...)
(multiple-value-prog1
(progn
(...)
(call-next-method))
(...)))

I find this rather ugly. So what I want to have is something like that.

(defmethod m :around (...)
(prog@
(...)
@(call-next-method)
(...)))

I think this is somewhat nicer. However, you have to admit that this
calls for generalization. ;-)

Please note that I am still in a kind of learning mode and this is
partly just for the fun of seeing if I have gotten things right. (Yeah,
I know, very selfish... ;)

Pascal Costanza

unread,
Nov 14, 2002, 12:49:15 PM11/14/02
to
Nils Goesche wrote:
> Pascal Costanza <cost...@web.de> writes:
>
>
>>I have written the following macro.
>
>
> [snip]
>
>
>>Its purpose is to allow returning values from somewhere in the
>>middle of a function.
>>

>
>

> What I don't like about it:

[several hard cases]

Thanks a lot for those. Here is a new version which should cover them.

(defun trans@ (list varsym)
(unless (consp list) (return-from trans@ list))

(let ((carl (car list))
(carln nil))

(case carl
((quote prog@) list)

(@ `((progn


(setf ,varsym
(multiple-value-list
,(trans@ (cadr list) varsym)))
(values-list ,varsym))

,@(trans@ (cddr list) varsym)))

(otherwise
(if (and (symbolp carl)
(setq carln (symbol-name carl))
(eq (aref carln 0) #\@))
(progn
(assert (not (eq (aref carln 1) #\#)) ()
"Reader macro immediately after @ in prog@.")
`((progn
(setf ,varsym
(multiple-value-list
,(read-from-string (subseq carln 1))))
(values-list ,varsym))
,@(trans@ (cdr list) varsym)))
`(,(trans@ carl varsym)
,@(trans@ (cdr list) varsym)))))))

(defmacro prog@ (&body body)
(let ((result (gensym)))
`(let ((,result nil))
,@(trans@ body result)
(values-list ,result))))


Anything else? ;)

Duane Rettig

unread,
Nov 14, 2002, 1:00:01 PM11/14/02
to
Pascal Costanza <cost...@web.de> writes:

> Hi folks,
>
> I have written the following macro.

[ ... ]

> Its purpose is to allow returning values from somewhere in the middle
> of a function.

[ ... ]

> The purpose of this posting is to check whether I have got this macro
> right. It seems to work well - but is there anything I might have
> overlooked? Any comments?

It looks like Nils has already found some problem cases. My functional
advice was going to be to test, test, test, but it seems Nils has done
some of that for you.

My other comment borders on a style issue; it is not about beauty or
ugliness, but about utility and liklihood of error (I am not sure what
exctly to call it). It's about your choice of marker symbol: I think
that '@ is not the best choice, because of what it makes the code look
like. To illustrate, re your example:

> (defmethod test :around ()
> (format t "around: ")
> @(call-next-method)
> (format t " :around"))

This looks like a mistake; it looks like you've forgotten a comma
(and, of course, a backquote, but the first-order code-read makes me
think "forgot a comma".

Perhaps a circumflex ("^") would be a better choice? This carries
some precedent, since the circumflex is used in format strings as
an a sort of ending device, and although it carries different semantics,
they are closer to those of @ usage, and it doesn't carry the baggage
of having Lisp reader syntax associated with it.

Perhaps there is an even better choice. I had thought of '<, but that
would leave one with either a feeling of a strange prefix math notation,
or else an imbalance with the human reader searching for the closing '>.

As I said, this borders on a style issue, and you are of course free
to stay with your choice. I'm trying to perform a lookahead to what
your code written in this style will look like to you 6 months after
you write it...

--
Duane Rettig du...@franz.com Franz Inc. http://www.franz.com/
555 12th St., Suite 1450 http://www.555citycenter.com/
Oakland, Ca. 94607 Phone: (510) 452-2000; Fax: (510) 452-0182

Kenny Tilton

unread,
Nov 14, 2002, 1:12:58 PM11/14/02
to

Pascal Costanza wrote:
> Kenny Tilton wrote:
>

>> Lawdy, how often does this come up? ...


>
>
> Thanks for your comments. Well, I have seen the following idiom.
>
> (defmethod m :around (...)
> (multiple-value-prog1
> (progn
> (...)
> (call-next-method))
> (...)))

Yes, we have one of those somewhere in our app. It's a big app, tho. :)

And like I said, that just means we have both before and after
processing around the meat of the function, nothing wrong with that (in
rare cases) except some visual confusion.

otoh, (+ 1 return-me 3) cries out for refactoring.

> Please note that I am still in a kind of learning mode and this is
> partly just for the fun of seeing if I have gotten things right.

I did wonder if that was part of the motivation, and a fine motivation
it is. Hopefully, tho, like Nixon you will conclude "We could do it, but
it would be wrong."

:)

Pascal Costanza

unread,
Nov 14, 2002, 1:28:09 PM11/14/02
to
Duane Rettig wrote:
> Pascal Costanza <cost...@web.de> writes:
>
>
>>Hi folks,
>>
>>I have written the following macro.
>
>
> [ ... ]
>
>
>>Its purpose is to allow returning values from somewhere in the middle
>>of a function.
>
>
> [ ... ]
>

> It looks like Nils has already found some problem cases. My functional


> advice was going to be to test, test, test, but it seems Nils has done
> some of that for you.

Yes, he actually helped me to see what I should be looking for...

> My other comment borders on a style issue; it is not about beauty or
> ugliness, but about utility and liklihood of error (I am not sure what
> exctly to call it). It's about your choice of marker symbol: I think
> that '@ is not the best choice, because of what it makes the code look
> like.

Well, it seems that all the nice symbols have already been used. I don't
like ^ because it's usually inconvenient to type, and reminds me of the
pointer symbol in Pascal. What about <>?

(prog<>
(...)
<>(...)
(...))

Or ~?

(prog~
(...)
~(...)
(...))

Barry Margolin

unread,
Nov 14, 2002, 1:49:31 PM11/14/02
to

One thing that bothers me about this macro: it looks like it doesn't nest
well. What does

(prog@
@ 'outer
(prog@
@ 'inner))

return? I think it *should* return OUTER, but I suspect it actually
returns INNER (I haven't tried it).

--
Barry Margolin, bar...@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Erik Naggum

unread,
Nov 14, 2002, 1:52:13 PM11/14/02
to
* Pascal Costanza

| I have written the following macro.

I think $ is a much better symbol to use for this. "Return on investment"
can be the mnemonic. @ connotes time and such for me. Using it up as an
internal marker makes it so much harder to use a print syntax for time.

--
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.

Erik Naggum

unread,
Nov 14, 2002, 1:58:52 PM11/14/02
to
* Pascal Costanza <cost...@web.de>

| Thanks for your comments. Well, I have seen the following idiom.
|
| (defmethod m :around (...)
| (multiple-value-prog1
| (progn
| (...)
| (call-next-method))
| (...)))
|
| I find this rather ugly. So what I want to have is something like that.
|
| (defmethod m :around (...)
| (prog@
| (...)
| @(call-next-method)
| (...)))
|
| I think this is somewhat nicer. However, you have to admit that this calls
| for generalization. ;-)

(defmethod m :around (...)
(...)
(multiple-value-prog1
(call-next-method)
(...)))

I fail to see the problem. Elsewhere, a simple `let´ form that captures
the value and returning is value at the end seems to do a much better job
at this:

(...)
(let (($ ...))
(... $ ...)
$)

If your value has no natural name, using a symbol like $ should be OK,
but you should really think of a good name for the value if it is used
elsewhere in the function.

Wade Humeniuk

unread,
Nov 14, 2002, 2:42:23 PM11/14/02
to
It might be easier just to do away with a special character
altogether and put a special function to return within the macro.

(defmacro prog-anywhere (&body body)
(let ((return-value (gensym)))
`(let ((,return-value nil))
(flet ((prog-return (value)
(setf ,return-value value)))
,@body)
,return-value)))

CL-USER 11 > (prog-anywhere
(if t
(1+ (prog-return 10))
(1- (prog-return 0))))
10

CL-USER 12 > (prog-anywhere
(if nil
(1+ (prog-return 10))
(1- (prog-return 0))))
0

CL-USER 13 >

The prog-anywhere can be renamed to anything one wants. I am
not sure how a VALUES return could be made to work. Also the
flet could be replaced with a macrolet if one is concerned
with generating anonymous functions all over the place.

Wade

Marco Antoniotti

unread,
Nov 14, 2002, 2:57:17 PM11/14/02
to

Pascal Costanza <cost...@web.de> writes:

Why not making it a special and local function or macro

(prog-escape
(...)
(escape (...))
(...))
?

--
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
715 Broadway 10th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://bioinformatics.cat.nyu.edu
"Hello New York! We'll do what we can!"
Bill Murray in `Ghostbusters'.

Duane Rettig

unread,
Nov 14, 2002, 3:00:01 PM11/14/02
to
Pascal Costanza <cost...@web.de> writes:

> Duane Rettig wrote:
>
> > My other comment borders on a style issue; it is not about beauty or
> > ugliness, but about utility and liklihood of error (I am not sure what
> > exctly to call it). It's about your choice of marker symbol: I think
> > that '@ is not the best choice, because of what it makes the code look
> > like.
>
> Well, it seems that all the nice symbols have already been used. I
> don't like ^ because it's usually inconvenient to type, and reminds me
> of the pointer symbol in Pascal. What about <>?

Hmm, on my keyboard the @ key is above the 2, and the ^ key is above the
6; they're both shifted, and on the top row, and so I don't view one
as more inconvenient than the other.

As for <>; they are also both shifted keys for me, although they are on
the bottom row, and there are two of them.

Frankly, though, I almost never look at actual typing convenience, but
rather what things look like.

> (prog<>
> (...)
> <>(...)
> (...))

Moving toward HTML, are we? :-)

> Or ~?
>
> (prog~
> (...)
> ~(...)
> (...))

Yuck.

Duane Rettig

unread,
Nov 14, 2002, 3:00:01 PM11/14/02
to
Pascal Costanza <cost...@web.de> writes:

> Kenny Tilton wrote:
>
> > Lawdy, how often does this come up? I'd forget prog@ and think about
> > refactoring. Mind you, I am way out on a limb here because I do not
> > know what you are up to over there.
>
> Thanks for your comments. Well, I have seen the following idiom.
>
> (defmethod m :around (...)
> (multiple-value-prog1
> (progn
> (...)
> (call-next-method))
> (...)))
>
> I find this rather ugly. So what I want to have is something like that.
>
> (defmethod m :around (...)
> (prog@
> (...)
> @(call-next-method)
> (...)))
>
> I think this is somewhat nicer. However, you have to admit that this
> calls for generalization. ;-)
>
>
> Please note that I am still in a kind of learning mode and this is
> partly just for the fun of seeing if I have gotten things
> right. (Yeah, I know, very selfish... ;)

You might also want to consider efficiency issues. Calls to
multiple-value-list are likely to cons, whereas performing the
above with :before and :after methods are more likely to be
done cons-free.

Also, although call-next-method is a powerful tool, it tends also to
be harder to optimize in effective-methods than straight :before and
:after methods.

Wade Humeniuk

unread,
Nov 14, 2002, 3:01:07 PM11/14/02
to

This can be even simpler and work in calls down the stack.

(defvar *prog-anywhere-return* nil)

(defun prog-return (value) (setf *prog-anywhere-return* value))

(defmacro prog-anywhere (&body body)
`(progn
,@body
*prog-anywhere-return*))

Wade

Barry Margolin

unread,
Nov 14, 2002, 3:11:19 PM11/14/02
to
In article <7iTA9.2731$3J1.2...@news1.telusplanet.net>,

Your previous version, with the FLET, addressed my issue of nesting these
things.

Using a global variable like this is actually worse than the OP's version.
Not only can't they nest lexically, they also can't nest dynamically.
E.g. the following won't work right:

(defun fun1 ()
(prog-anywhere
@ 'fun1
(fun2)))

(defun fun2 ()
(prog-anywhere
@ 'fun2))

(fun1) should return FUN1, but it will return FUN2. This is the type of
referential transparency problem that lexical scoping was designed to
solve.

Marcus Breiing

unread,
Nov 14, 2002, 3:19:40 PM11/14/02
to
Duane Rettig <du...@franz.com> wrote:

> Hmm, on my keyboard the @ key is above the 2, and the ^ key is above
> the 6; they're both shifted, and on the top row, and so I don't view
> one as more inconvenient than the other.

On my keyboard, as on Pascal Costanza's (I guess), ^ is a dead key.
So you type ^+Space to get ^. At least, nowadays it actually *works*
like that for me. I had a setup once where typing this invariably got
me ^^, so I'd have to type ^+Space+Backspace to get a single caret.
Drôle.


--
Marcus Breiing
mailto:news-g...@breiing.com (will expire)

Joe Marshall

unread,
Nov 14, 2002, 3:21:03 PM11/14/02
to
Pascal Costanza <cost...@web.de> writes:

> I have written the following macro.

> [elided]

I can see where you might want to get at the nth form in a progn, but
grabbing stuff out of the middle of an application is just ugly. (not
to mention the scoping problems Barry pointed out.) How about
something like this:

(mvprog1-with-prelude ((setq *x* 'foo)
(format t "foo!"))
(call-next-method)
(format t "bar!"))

No funky identifiers, no scoping and nesting problems.

If you find that you need the values from the middle of an
application, and you don't want to rewrite the code, you can do this:

(let (retval)
(...)
(format t (setq retval "Hello world."))
(...)
retval)

This is pretty ugly, too, but then the next person who reads the code
won't have to look at your macro to try to figure out what the atsign
is doing.

Marcus Breiing

unread,
Nov 14, 2002, 3:30:28 PM11/14/02
to
Pascal Costanza <cost...@web.de> wrote:

> Anything else? ;)

Sure ;-)

What do you think

(prog@
(let ((@ 2))
@))

should return (once you get rid of the macroexpansion-time errors)?

Hey, when you're done with prog@, don't forget to abstract-out the
more interesting parts. Maybe call it WALKER?

Erik Naggum

unread,
Nov 14, 2002, 3:44:58 PM11/14/02
to
* Pascal Costanza

| I don't like ^ because it's usually inconvenient to type, and reminds me
| of the pointer symbol in Pascal.

This is one case where it makes sense to think about something even
though it gives you painful associations.

^ is unshifted above the Y on my keyboard...

Wade Humeniuk

unread,
Nov 14, 2002, 3:46:21 PM11/14/02
to

"Barry Margolin" <bar...@genuity.net> wrote in message
news:HrTA9.29$Xq1....@paloalto-snr1.gtei.net...

> Your previous version, with the FLET, addressed my issue of nesting these
> things.
>
> Using a global variable like this is actually worse than the OP's version.
> Not only can't they nest lexically, they also can't nest dynamically.
> E.g. the following won't work right:
>
> (defun fun1 ()
> (prog-anywhere
> @ 'fun1
> (fun2)))
>
> (defun fun2 ()
> (prog-anywhere
> @ 'fun2))
>
> (fun1) should return FUN1, but it will return FUN2. This is the type of
> referential transparency problem that lexical scoping was designed to
> solve.

Oops, I guess that should be

(defvar *prog-anywhere-return* nil)

(defun prog-return (value) (setf *prog-anywhere-return* value))

(defmacro prog-anywhere (&body body)
`(let (*prog-anywhere-return*)
,@body
*prog-anywhere-return*))

CL-USER 3 > (defun fun2 ()
(prog-anywhere
(prog-return 'fun2)))

FUN2

CL-USER 4 > (defun fun1 ()
(prog-anywhere
(prog-return 'fun1)
(fun2)))
FUN1

CL-USER 5 > (fun1)
FUN1

CL-USER 6 >

Wade

Erik Naggum

unread,
Nov 14, 2002, 3:52:07 PM11/14/02
to
* Marcus Breiing

| On my keyboard, as on Pascal Costanza's (I guess), ^ is a dead key.
| So you type ^+Space to get ^. At least, nowadays it actually *works*
| like that for me. I had a setup once where typing this invariably got
| me ^^, so I'd have to type ^+Space+Backspace to get a single caret.

If you edit text for human beings, this is not an insane keyboard layout.
If you edit code, anything that keeps all of ASCII from being accessible
without contortions is rabidly insane. Programmers who cannot figure out
how to unbraindamage their keyboards should become journalists or
something where accuracy and intelligence are inconveniences.

On Norwegian keyboards, {}[] are reachable with AltGr and a digit key on
the left hand. If you write in any language using the C syntax template,
and you have /not/ changed to a US keyboard layout to get rid of this
monstrous insanity, you deserve the wrists you are soon going to get.
(But if someone wishes to argue against Java and C++ in Norway based on
this incredible braindamage, I shall probably support them.)

Nils Goesche

unread,
Nov 14, 2002, 3:54:51 PM11/14/02
to
Marcus Breiing <news-g...@breiing.com> writes:

> Duane Rettig <du...@franz.com> wrote:
>
> > Hmm, on my keyboard the @ key is above the 2, and the ^ key is above
> > the 6; they're both shifted, and on the top row, and so I don't view
> > one as more inconvenient than the other.
>
> On my keyboard, as on Pascal Costanza's (I guess), ^ is a dead key.
> So you type ^+Space to get ^. At least, nowadays it actually *works*
> like that for me. I had a setup once where typing this invariably got
> me ^^, so I'd have to type ^+Space+Backspace to get a single caret.
> Drôle.

$ setxkbmap -layout us

It really pays off in the long run.

Erik Naggum

unread,
Nov 14, 2002, 3:55:21 PM11/14/02
to
* "Wade Humeniuk" <wa...@nospam.nowhere>

Make that

(defmacro prog-anywhere (&body body)
`(let (*prog-anywhere-return*)
,@body
*prog-anywhere-return*))

Marcus Breiing

unread,
Nov 14, 2002, 4:07:16 PM11/14/02
to
Erik Naggum <er...@naggum.no> wrote:

> If you edit code, anything that keeps all of ASCII from being
> accessible without contortions is rabidly insane.

Hitting two or even three keys in sequence to get an operator from
your favorite programming language isn't really *rabidly* insane.
Hell, if it were, we'd all have to switch to Paul Graham's Arc, which
seems to be based on that idea:-)

That said, the one place where I actually had to type the caret more
than once in a blue moon was in Gnus, to move up the reference chain.
I changed that keybinding, and that was it.

What isn't good thinking IMHO is for a language *designer* to reject a
syntax that would be really nice just because he can't type it
conveniently using his *current* setup. That'd be like specifying a
fixed huffman tree for ZIP and expect people to adjust their
compressible material accordingly.

Marcus Breiing

unread,
Nov 14, 2002, 4:15:05 PM11/14/02
to
Nils Goesche <car...@cartan.de> wrote:

> $ setxkbmap -layout us

Well, I use Win2K as a device driver so that wouldn't work. However,
on this system I can hit alt-shift to switch between German and US
layout on the fly. Nifty.

I also do major-mode dependent remapping of ö,ä and ü, but that's
about all the keyboard mangling I can stomach. I like to retain the
ability to work on other people's computers. I have almost *lost* the
ability to use non-RPN pocket calculators, and that bothers me,
sometimes:-)

Erik Naggum

unread,
Nov 14, 2002, 4:26:34 PM11/14/02
to
* Marcus Breiing

| That'd be like specifying a fixed huffman tree for ZIP and expect people
| to adjust their compressible material accordingly.

Good analogy.

Joe Marshall

unread,
Nov 14, 2002, 4:30:53 PM11/14/02
to
Erik Naggum <er...@naggum.no> writes:

> On Norwegian keyboards, {}[] are reachable with AltGr and a digit key on
> the left hand. If you write in any language using the C syntax template,
> and you have /not/ changed to a US keyboard layout to get rid of this
> monstrous insanity, you deserve the wrists you are soon going to get.

But what about trigrams......?

Pascal Costanza

unread,
Nov 14, 2002, 5:05:02 PM11/14/02
to
Marcus Breiing wrote:
> Pascal Costanza <cost...@web.de> wrote:
>
>
>>Anything else? ;)
>
>
> Sure ;-)
>
> What do you think
>
> (prog@
> (let ((@ 2))
> @))
>
> should return (once you get rid of the macroexpansion-time errors)?

Oh dear! ;)

> Hey, when you're done with prog@, don't forget to abstract-out the
> more interesting parts. Maybe call it WALKER?

I haven't exposed myself to tree walkers yet - could you or someone give
me pointer where to read about them?


Thanks,
Pascal

--
Given any rule, however ‘fundamental’ or ‘necessary’ for science, there
are always circumstances when it is advisable not only to ignore the
rule, but to adopt its opposite. - Paul Feyerabend

Pascal Costanza

unread,
Nov 14, 2002, 5:32:06 PM11/14/02
to
Barry Margolin wrote:
> One thing that bothers me about this macro: it looks like it doesn't nest
> well. What does
>
> (prog@
> @ 'outer
> (prog@
> @ 'inner))
>
> return? I think it *should* return OUTER, but I suspect it actually
> returns INNER (I haven't tried it).

Kenny's recent post has already convinced me that I shouldn't traverse
deeply into the forms but only do a shallow traversal. Your example is
another good argument in that direction.

With a shallow traversal things get considerably simpler.

(defmacro prog! (&body body)
(let ((result (gensym)))
`(let ((,result nil))
(macrolet ((! (form)
`(progn
(setq ,',result
(multiple-value-list ,form))
(values-list ,',result))))
,@body
(values-list ,result)))))

So now we can do the following.

(prog!
(...)
(! (...))
(...))

I like this more than other proposals with prog1/progn or (let ...)
because there, the before and after parts are not at the same level.
(This is only an aesthetical issue.)

I like Erik's proposal to use the $ sign for my macro. The ! might give
Schemers a headache. ;)

I think a proper name that includes "return" (like prog-return) instead
of a marker like ! or $ can be misleading because "return" usually means
to return immediately.

About the consing of multiple-value-list: I guess a good solution for
that would be to provide two versions, prog$ and multiple-value-prog$.
(So the above macro would be the multiple-value-prog$ version.)

Thanks again for all the comments.

Thomas F. Burdick

unread,
Nov 14, 2002, 5:40:04 PM11/14/02
to
Erik Naggum <er...@naggum.no> writes:

> * Pascal Costanza
> | I don't like ^ because it's usually inconvenient to type, and reminds me
> | of the pointer symbol in Pascal.
>
> This is one case where it makes sense to think about something even
> though it gives you painful associations.
>
> ^ is unshifted above the Y on my keyboard...

Hmm, Pascal has painful memories of Pascal ...

If you're looking for positive associations, SmallTalk writes
(return foo)
as
^foo
and it's got this nice up-arrow feel to it

--
/|_ .-----------------------.
,' .\ / | No to Imperialist war |
,--' _,' | Wage class war! |
/ / `-----------------------'
( -. |
| ) |
(`-. '--.)
`. )----'

Nils Goesche

unread,
Nov 14, 2002, 5:47:03 PM11/14/02
to
Pascal Costanza <cost...@web.de> writes:

> Marcus Breiing wrote:

> > Hey, when you're done with prog@, don't forget to
> > abstract-out the more interesting parts. Maybe call it
> > WALKER?
>
> I haven't exposed myself to tree walkers yet - could you or
> someone give me pointer where to read about them?

Heh -- I gave you those examples to help you understand that what
you need is a fully-fledged code walker /if/ you really want to
descend into the code to replace the occurrences of @. Just
google for ``code walker´´ to find one, or do (apropos "walk")
because many Lisp implementations already contain one. However,
all the PROG* forms return simply one of their ``top-level´´
forms -- if you do the same, your macro would be much easier to
write -- just don't descend into the code.

Regards,
--
Nils Gösche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0

Erik Naggum

unread,
Nov 14, 2002, 5:49:19 PM11/14/02
to
* Joe Marshall
| But what about trigrams......?

The whole trigram concept was invented by a particularly dishonest Danish
nutjob who did not want to change his keyboard. Now, C sports bigrams,
one of his ideas that would have been shot down if anybody had bothered
to check his claim that "X, Y, and Z used it", which he successfully used
to fool at least 4 different standardization organizations by arguing
that the others used it and running around fast enough to ensure that
that argument was self-sustaining, however circular. It was an amazing
example of how it is possible to use the implicit trust in decisions made
standardization organizations can be exploited. Even the IETF was used
in this political game and published a horribly bug-ridden RFC that is
/completely/ worthless.

Pascal Costanza

unread,
Nov 14, 2002, 5:53:48 PM11/14/02
to
Nils Goesche wrote:
> Pascal Costanza <cost...@web.de> writes:
>
>
>>Marcus Breiing wrote:
>
>
>>>Hey, when you're done with prog@, don't forget to
>>>abstract-out the more interesting parts. Maybe call it
>>>WALKER?
>>
>>I haven't exposed myself to tree walkers yet - could you or
>>someone give me pointer where to read about them?
>
>
> Heh -- I gave you those examples to help you understand that what
> you need is a fully-fledged code walker /if/ you really want to
> descend into the code to replace the occurrences of @. Just
> google for ``code walker´´ to find one, or do (apropos "walk")
> because many Lisp implementations already contain one.

Of course - sorry!

Nils Goesche

unread,
Nov 14, 2002, 6:16:03 PM11/14/02
to
Pascal Costanza <cost...@web.de> writes:

> Nils Goesche wrote:
> > Pascal Costanza <cost...@web.de> writes:
> >
> >>Marcus Breiing wrote:
> >
> >>>Hey, when you're done with prog@, don't forget to
> >>>abstract-out the more interesting parts. Maybe call it
> >>>WALKER?
> >>
> >>I haven't exposed myself to tree walkers yet - could you or
> >>someone give me pointer where to read about them?
> > Heh -- I gave you those examples to help you understand that what
> > you need is a fully-fledged code walker /if/ you really want to
> > descend into the code to replace the occurrences of @. Just
> > google for ``code walker´´ to find one, or do (apropos "walk")
> > because many Lisp implementations already contain one.
>
> Of course - sorry!

Wieso sorry? Nur falls Du es nicht weiszt, ``Heh´´ ist Englisch
fuer ``Hehe´´, nicht ``Hey!´´ :-)

Bis denne,

Nils Goesche

unread,
Nov 14, 2002, 6:53:21 PM11/14/02
to
Erik Naggum <er...@naggum.no> writes:

> * Joe Marshall
> | But what about trigrams......?
>
> The whole trigram concept was invented by a particularly
> dishonest Danish nutjob who did not want to change his
> keyboard.

Pardon my ignorance, but google didn't help much in this case.
What are trigrams?

Regards,

Nils Goesche

unread,
Nov 14, 2002, 6:55:14 PM11/14/02
to
I <n...@cartan.de> wrote:

[German gibberish]

Sorry. Was supposed to be mailed. Maybe I should remap the `F´
or `R´ key to some different place on my keyboard...

Regards,

Erik Naggum

unread,
Nov 14, 2002, 7:11:39 PM11/14/02
to
* Nils Goesche

| Pardon my ignorance, but google didn't help much in this case.
| What are trigrams?

A way for really stupid people to write C without changing to a rational
keyboard layout. I see now that they are actually called "trigraphs".
In brief, the following replacements are made at a very early stage in
the processing of the input files.

??= --> #
??( --> [
??/ --> \
??) --> ]
??' --> ^
??< --> {
??! --> |
??> --> }
??- --> ~

As if this was not enough, we also have support for "digraphs":

In all aspects of the language, the six tokens

<: :> <% %> %: %:%:

behave, respectively, the same as the six tokens

[ ] { } # ##

except for their spelling.

The most significant consequence of these stunts is that you cannot hold
obfuscated C contests, anymore.

Nils Goesche

unread,
Nov 14, 2002, 9:23:03 PM11/14/02
to
Erik Naggum <er...@naggum.no> writes:

> * Nils Goesche
> | Pardon my ignorance, but google didn't help much in this case.
> | What are trigrams?
>
> A way for really stupid people to write C without changing to
> a rational keyboard layout. I see now that they are actually
> called "trigraphs".

Ah, sure. I know these, of course. Just one of the many things
the experienced C programmer gets bitten by once in a
while... :-( I don't remember a specific example, but I am
certain that there was more than one occasion I or a coworker got
bitten by this -- made for very hard to find bugs (always end
your exciting debug messages and comments with ?!, not with ??).

I have indeed been wondering all the time how something stupid
like this could ever enter the C standard. Do you know the
story? Is it written down somewhere?

Erik Naggum

unread,
Nov 14, 2002, 9:50:33 PM11/14/02
to
* Nils Goesche <n...@cartan.de>

| I have indeed been wondering all the time how something stupid like this
| could ever enter the C standard. Do you know the story? Is it written
| down somewhere?

I just told the story.

Gabe Garza

unread,
Nov 14, 2002, 9:53:22 PM11/14/02
to
"Wade Humeniuk" <wa...@nospam.nowhere> writes:

> The prog-anywhere can be renamed to anything one wants. I am
> not sure how a VALUES return could be made to work. Also the
> flet could be replaced with a macrolet if one is concerned
> with generating anonymous functions all over the place.

Here's something along these lines that would allow multiple
values:

(defmacro prog-anywhere (returner-name &body body)
(let ((return-values-list (gensym "RETURN-VALUES-LIST")))
`(let (,return-values-list)
(flet ((,returner-name (&rest values)
(setf ,return-values-list values)))
,@body
(values-list ,return-values-list)))))

* (prog-anywhere return-outer
(multiple-value-bind (a b)
(prog-anywhere return-inner
1
(return-inner 2 3)
4
(return-outer 5 6)
7)
(print (cons a b))))
(2 . 3)
5
6
*

Gabe Garza

Nils Goesche

unread,
Nov 14, 2002, 10:18:16 PM11/14/02
to
Erik Naggum <er...@naggum.no> writes:

> * Nils Goesche <n...@cartan.de>
> | I have indeed been wondering all the time how something
> | stupid like this could ever enter the C standard. Do you
> | know the story? Is it written down somewhere?
>
> I just told the story.

Yes, but I still don't know the name of the dane in question :-)

Erik Naggum

unread,
Nov 14, 2002, 10:40:40 PM11/14/02
to
* Nils Goesche

| Yes, but I still don't know the name of the dane in question :-)

RFC 1345 should be a fairly good start in this regard.

Wade Humeniuk

unread,
Nov 14, 2002, 11:50:39 PM11/14/02
to

"Gabe Garza" <g_g...@ix.netcom.com> wrote in message news:87d6p7h...@ix.netcom.com...

> (defmacro prog-anywhere (returner-name &body body)
> (let ((return-values-list (gensym "RETURN-VALUES-LIST")))
> `(let (,return-values-list)
> (flet ((,returner-name (&rest values)
> (setf ,return-values-list values)))
> ,@body
> (values-list ,return-values-list)))))
>
> * (prog-anywhere return-outer
> (multiple-value-bind (a b)
> (prog-anywhere return-inner
> 1
> (return-inner 2 3)
> 4
> (return-outer 5 6)
> 7)
> (print (cons a b))))
> (2 . 3)
> 5
> 6
> *

Nice touch with the returner-name. I get that mind altered feeling
with the example. It feels like it would be useful in real life (a kind of
a space connected with a whole bunch of wormholes), though I am
don't know where. Adds a new take on the idea of spaghetti code.


Wade

Pascal Costanza

unread,
Nov 15, 2002, 2:09:15 AM11/15/02
to
Gabe Garza wrote:
> "Wade Humeniuk" <wa...@nospam.nowhere> writes:
>
>
>>The prog-anywhere can be renamed to anything one wants. I am
>>not sure how a VALUES return could be made to work. Also the
>>flet could be replaced with a macrolet if one is concerned
>>with generating anonymous functions all over the place.
>
>
> Here's something along these lines that would allow multiple
> values:
>
> (defmacro prog-anywhere (returner-name &body body)
> (let ((return-values-list (gensym "RETURN-VALUES-LIST")))
> `(let (,return-values-list)
> (flet ((,returner-name (&rest values)
> (setf ,return-values-list values)))
> ,@body
> (values-list ,return-values-list)))))

Yes, but the following still doesn't work.

> (prog-anywhere !
5 6 7
(! (values 42 43 44))
8 9 10)
42

To be able to deal with multiple values is especially important when you
want to call a (predefined) function that returns multiple values.

Another question: I have seen (gensym "SOME-NAME") every now and then.
My understanding of this usage of gensym is that the generated symbols
aren't strictly unique anymore, right? Why do people still use this idiom?

Gabe Garza

unread,
Nov 15, 2002, 2:32:41 AM11/15/02
to
Pascal Costanza <cost...@web.de> writes:
> Yes, but the following still doesn't work.
>
> > (prog-anywhere !
> 5 6 7
> (! (values 42 43 44))
> 8 9 10)
> 42
>
> To be able to deal with multiple values is especially important when
> you want to call a (predefined) function that returns multiple values.

If that's the semantics you want you could always use:

(defmacro multiple-value-prog-anywhere (returner-name &body body)


(let ((return-values-list (gensym "RETURN-VALUES-LIST")))
`(let (,return-values-list)

(macrolet ((,returner-name (&body body)
`(setf ,',return-values-list
(multiple-value-list ,@body))))
,@body
(values-list ,return-values-list)))))

* (multiple-value-prog-anywhere !


5 6 7
(! (values 42 43 44))
8 9 10)
42

43
44
*

> Another question: I have seen (gensym "SOME-NAME") every now and
> then. My understanding of this usage of gensym is that the generated
> symbols aren't strictly unique anymore, right? Why do people still use
> this idiom?

The generated symbols are unique--that's the whole point of gensym. I
assume you're confused over giving it a name...

In this case, I used it for ease of debugging. Any worthy Common Lisp
environment will have a facility for macroexpanding a form so you can
see what your macros are expanding to. For example, in ilisp if I put
the cursor before the previous example and type M-x macroexpand-lisp
the following output is displayed:

(LET (#:RETURN-VALUES-LIST2158)
(MACROLET ((! (&BODY BODY)
`(SETF #:RETURN-VALUES-LIST2158 (MULTIPLE-VALUE-LIST ,@BODY))))
5
6
7
(! (VALUES 42 43 44))
8
9
10
(VALUES-LIST #:RETURN-VALUES-LIST2158)))

In this case, it's not that necessary. But in more complicated
macros, or nested macros, etc., it can be.

Gabe Garza

Gabe Garza

unread,
Nov 15, 2002, 2:36:15 AM11/15/02
to
Pascal Costanza <cost...@web.de> writes:
> Yes, but the following still doesn't work.
>
> > (prog-anywhere !
> 5 6 7
> (! (values 42 43 44))
> 8 9 10)
> 42
>
> To be able to deal with multiple values is especially important when
> you want to call a (predefined) function that returns multiple values.

If that's the semantics you want you could always use:

(defmacro multiple-value-prog-anywhere (returner-name &body body)


(let ((return-values-list (gensym "RETURN-VALUES-LIST")))
`(let (,return-values-list)

(macrolet ((,returner-name (form)
`(setf ,',return-values-list
(multiple-value-list ,form))))
,@body
(values-list ,return-values-list)))))

* (multiple-value-prog-anywhere !


5 6 7
(! (values 42 43 44))
8 9 10)
42

43
44
*

> Another question: I have seen (gensym "SOME-NAME") every now and
> then. My understanding of this usage of gensym is that the generated
> symbols aren't strictly unique anymore, right? Why do people still use
> this idiom?

The generated symbols are unique--that's the whole point of gensym. I


assume you're confused over giving it a name...

In this case, I used it for ease of debugging. Any worthy Common Lisp
environment will have a facility for macroexpanding a form so you can
see what your macros are expanding to. For example, in ilisp if I put
the cursor before the previous example and type M-x macroexpand-lisp
the following output is displayed:

(LET (#:RETURN-VALUES-LIST2158)
(MACROLET ((! (&BODY BODY)
`(SETF #:RETURN-VALUES-LIST2158 (MULTIPLE-VALUE-LIST ,@BODY))))
5
6
7

(! (VALUES 42 43 44))
8
9

Pascal Costanza

unread,
Nov 15, 2002, 3:20:46 AM11/15/02
to
Gabe Garza wrote:
> Pascal Costanza <cost...@web.de> writes:
>

>>Another question: I have seen (gensym "SOME-NAME") every now and
>>then. My understanding of this usage of gensym is that the generated
>>symbols aren't strictly unique anymore, right? Why do people still use
>>this idiom?
>
>
> The generated symbols are unique--that's the whole point of gensym. I
> assume you're confused over giving it a name...
>

No, it's about the uniqueness. In the example you have given, it may be
the case that RETURN-VALUES-LIST2158 has already existed before. As far
as I understand the HyperSpec a Common Lisp implementation is not
required to take the necessary precautions against this case (whereas
(gensym) without a string argument is always guaranteed to be unique).
Right?

> (LET (#:RETURN-VALUES-LIST2158)
> (MACROLET ((! (&BODY BODY)
> `(SETF #:RETURN-VALUES-LIST2158 (MULTIPLE-VALUE-LIST ,@BODY))))
> 5
> 6
> 7
> (! (VALUES 42 43 44))
> 8
> 9
> 10
> (VALUES-LIST #:RETURN-VALUES-LIST2158)))

Pascal

Christophe Rhodes

unread,
Nov 15, 2002, 4:08:46 AM11/15/02
to
Pascal Costanza <cost...@web.de> writes:

> Gabe Garza wrote:
> > Pascal Costanza <cost...@web.de> writes:
> >
>
> >>Another question: I have seen (gensym "SOME-NAME") every now and
> >>then. My understanding of this usage of gensym is that the generated
> >>symbols aren't strictly unique anymore, right? Why do people still use
> >>this idiom?
> > The generated symbols are unique--that's the whole point of gensym.
> > I
> > assume you're confused over giving it a name...
> >
>
> No, it's about the uniqueness. In the example you have given, it may
> be the case that RETURN-VALUES-LIST2158 has already existed before. As
> far as I understand the HyperSpec a Common Lisp implementation is not
> required to take the necessary precautions against this case (whereas
> (gensym) without a string argument is always guaranteed to be
> unique). Right?

Wrong.

A symbol with the name RETURN-VALUES-LIST2158 may already have
existed; however, it is a different symbol from the one returned by
gensym. The CLHS page on gensym makes this clear, when it says that
the return value is a "fresh, uninterned symbol".

* '#:foo-1 -> #:FOO-1
* (setf *gensym-counter* 1) -> 1
* (gensym "FOO-") -> #:FOO-1
* (eq * ***) -> NIL

Cheers,

Christophe
--
http://www-jcsu.jesus.cam.ac.uk/~csr21/ +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%") (pprint #36rJesusCollegeCambridge)

Pascal Costanza

unread,
Nov 15, 2002, 5:06:43 AM11/15/02
to

Now I am really confused. How does a macro treat uninterned symbols, how
are they evaluated.

I have tried the following.

(defmacro test ()
(let ((bla #:bla))
`(let ((,bla '(1 2 3))
(pprint ,bla))))

> (test)
(1 2 3)

> (macroexpand +)
(LET ((#:BLA (QUOTE (1 2 3)))) (PPRINT #:BLA))

> (LET ((#:BLA (QUOTE (1 2 3)))) (PPRINT #:BLA))
Error: The variable #:BLA is unbound.

Huh?!? Of course, #:BLA is an uninterned symbol, but why does the macro
'test work in the first place?

Then again:

(defmacro test ()
`(let ((#:BLA '(1 2 3)))
(pprint #:BLA)))

> (test)
Error: The variable #:BLA is unbound.

?!?

I have tried to find a clue in the HyperSpec sections about macros,
symbols, evaluation, backquote and even packages, but I haven't found an
explanation. So basically I am stuck. What's going on here?


Pascal

--
Pascal Costanza University of Bonn
mailto:cost...@web.de Institute of Computer Science III
http://www.pascalcostanza.de Römerstr. 164, D-53117 Bonn (Germany)

Christophe Rhodes

unread,
Nov 15, 2002, 5:16:00 AM11/15/02
to
Pascal Costanza <cost...@web.de> writes:

Hmm. Rewriting for the sake of posterity:


(defmacro test ()
(let ((bla '#:bla))

`(let ((,bla '(1 2 3)))
(pprint ,bla))))
Then
(macroexpand '(test))
gives
(LET ((#:BLA '(1 2 3)))
(PPRINT #:BLA))
So, why does this not work when typed in? Well, think about object
identity. In the macroexpansion, the two things that have printed as
#:BLA are the same symbol; if you type this in, you get two different
uninterned symbols with the name "BLA". To see this:
(setf *print-circle* t)
(macroexpand '(test))
gives
(LET ((#1=#:BLA '(1 2 3)))
(PPRINT #1#))

Two different symbols can have the same name, and can print the same.

Pascal Costanza

unread,
Nov 15, 2002, 5:27:33 AM11/15/02
to
Christophe Rhodes wrote:
> Pascal Costanza <cost...@web.de> writes:

>>Now I am really confused. How does a macro treat uninterned symbols,
>>how are they evaluated.
>>
>
>

> Hmm. Rewriting for the sake of posterity:
> (defmacro test ()
> (let ((bla '#:bla))
> `(let ((,bla '(1 2 3)))
> (pprint ,bla))))

Er, yes, that's what I meant.

> Then
> (macroexpand '(test))
> gives
> (LET ((#:BLA '(1 2 3)))
> (PPRINT #:BLA))
> So, why does this not work when typed in? Well, think about object
> identity. In the macroexpansion, the two things that have printed as
> #:BLA are the same symbol; if you type this in, you get two different
> uninterned symbols with the name "BLA".

Oh dear - yes, that's clear as daylight! Now I also understand why
(gensym "SOME-NAME") is safe.

Thanks a lot indeed!

Frode Vatvedt Fjeld

unread,
Nov 15, 2002, 5:31:32 AM11/15/02
to
Pascal Costanza <cost...@web.de> writes:

> Now I am really confused. How does a macro treat uninterned symbols,
> how are they evaluated.

Just like any other symbols. It is mostly the reader and printer that
deals specially with uninterned symbols:

(eq '#:foo '#:foo) => NIL

--
Frode Vatvedt Fjeld

Marco Antoniotti

unread,
Nov 15, 2002, 2:50:14 PM11/15/02
to

Pascal Costanza <cost...@web.de> writes:

What about SAVE-FOR-RETURN ?

I am personally wary of using simgle character markers as they may be
used as macro characters by somebody else.

Cheers

--
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
715 Broadway 10th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://bioinformatics.cat.nyu.edu
"Hello New York! We'll do what we can!"
Bill Murray in `Ghostbusters'.

Pascal Costanza

unread,
Nov 15, 2002, 4:10:53 PM11/15/02
to
Marco Antoniotti wrote:
> Pascal Costanza <cost...@web.de> writes:
>

>>I think a proper name that includes "return" (like prog-return)
>>instead of a marker like ! or $ can be misleading because "return"
>>usually means to return immediately.
>
>
> What about SAVE-FOR-RETURN ?
>
> I am personally wary of using simgle character markers as they may be
> used as macro characters by somebody else.

You're right - on the other hand, SAVE-FOR-RETURN is quite long. What
about LIFT?

Here is the current version of my set of macros, in case anyone is
interested. I think that I have successfully balanced many of the forces
that were mentioned in this thread.

(defmacro multiple-value-progl (mark &body body)
(let ((result (gensym "RESULT-")))
`(let (,result)
(macrolet ((,mark (form)


`(progn
(setq ,',result
(multiple-value-list ,form))
(values-list ,',result))))
,@body
(values-list ,result)))))

(defmacro progl (mark &body body)
(let ((result (gensym "RESULT-")))
`(let ((,result nil))
(macrolet ((,mark (form) `(setq ,',result ,form)))
,@body
,result))))

(defmacro multiple-value-prog-lift (&body body)
`(multiple-value-progl lift ,@body))

(defmacro prog-lift (&body body)
`(progl lift ,@body))


So now the default case is as follows.

(prog-lift
(before ...)
(lift (actual-result ...))
(after ...))

...but you can also have:

(progl outer-lift
(...)
(progl inner-lift)
(...)
(outer-lift (...))
(inner-lift (...))
(...))
(...))

And all of these optionally with multiple values.

Did I already mention that Common Lisp is a f**king great language? ;-)

Kalle Olavi Niemitalo

unread,
Nov 15, 2002, 11:18:41 PM11/15/02
to
Pascal Costanza <cost...@web.de> writes:

> (progl outer-lift

I first read that as "prog1". I had not read a real "1" in this
font today and didn't remember what it looked like. Perhaps a
different name would be better.

Pascal Costanza

unread,
Nov 16, 2002, 7:17:00 AM11/16/02
to

Oh dear - yes, I haven't thought of that. So I switch to prog$.

Michael Hudson

unread,
Nov 19, 2002, 7:25:13 AM11/19/02
to
Marco Antoniotti <mar...@cs.nyu.edu> writes:

> I am personally wary of using simgle character markers as they may
> be used as macro characters by somebody else.

Something that's faintly bothered me for a while is wondering how you
cope with using two different lisp packages that use the same macro
character for different things. Is this ever a problem in practice?

Cheers,
M.

--
: Giant screaming pieces of excrement, they are.
I have a feeling that some of the people in here have a
MUCH more exciting time relieving themselves than I do.
-- Mike Sphar & Dave Brown, asr

Oleg

unread,
Nov 19, 2002, 7:47:55 AM11/19/02
to
Michael Hudson wrote:

> Marco Antoniotti <mar...@cs.nyu.edu> writes:
>
>> I am personally wary of using simgle character markers as they may
>> be used as macro characters by somebody else.
>
> Something that's faintly bothered me for a while is wondering how you
> cope with using two different lisp packages that use the same macro
> character for different things. Is this ever a problem in practice?
>

rename-package

Oleg

Tim Bradshaw

unread,
Nov 19, 2002, 8:34:03 AM11/19/02
to
* Michael Hudson wrote:

> Something that's faintly bothered me for a while is wondering how you
> cope with using two different lisp packages that use the same macro
> character for different things. Is this ever a problem in practice?

I think it is, and I think the answer is you really don't cope. I try
and make code I write which defines readmacros check to see if they
are already defined, and complain in that case.

--tim

Marco Antoniotti

unread,
Nov 19, 2002, 8:39:44 AM11/19/02
to

Michael Hudson <m...@python.net> writes:

> Marco Antoniotti <mar...@cs.nyu.edu> writes:
>
> > I am personally wary of using simgle character markers as they may
> > be used as macro characters by somebody else.
>
> Something that's faintly bothered me for a while is wondering how you
> cope with using two different lisp packages that use the same macro
> character for different things. Is this ever a problem in practice?

I think it is fine as long as you advertise it clearly and you set up
your read tables accordingly. E.g. it used to be cutsomary practice
to write Theorem Provers in Lisp and denote variables ("logical
variables" that is) with the notation `?var'. The understanding being
that this would translate into something like

?var ==> #<VARIABLE var>

This means that if I am using a certain system which I know uses a
peculiar macro character, then I know what to expect.

Pragmatically, I think that macro characters are useful for special
languages which are used in circumscribed loci (for lack of a better
word). E.g. if I write a file containing a specialized language and I
have full control in the way I READ it, then I am relatively safe.

Of course all of this does not quite answer your question. IMHO what
has happened is that CLers know that macro charcaters are to be used
sparingly, therefore, no major clashes have happened in the past in
mixing and matching separate libraries.

Of course YMMV.

Marco Antoniotti

unread,
Nov 19, 2002, 8:45:43 AM11/19/02
to

Oleg <oleg_i...@myrealbox.com> writes:

RENAME-PACKAGE does not apply in this case. The "space" of macro
characters is the read table, and there are no provisions to change it
at read time, short of doing

#.(setf *readtable* my-readtable)

(which - of course - is affected by *READ-EVAL*).

Michael Hudson

unread,
Nov 19, 2002, 8:36:10 AM11/19/02
to
Oleg <oleg_i...@myrealbox.com> writes:

No, I said "macro character", not "package name".

Cheers,
M.

--
ZAPHOD: Listen three eyes, don't try to outwierd me, I get stranger
things than you free with my breakfast cereal.
-- The Hitch-Hikers Guide to the Galaxy, Episode 7

Raymond Wiker

unread,
Nov 19, 2002, 9:18:04 AM11/19/02
to
Marco Antoniotti <mar...@cs.nyu.edu> writes:

> RENAME-PACKAGE does not apply in this case. The "space" of macro
> characters is the read table, and there are no provisions to change it
> at read time, short of doing
>
> #.(setf *readtable* my-readtable)
>
> (which - of course - is affected by *READ-EVAL*).

Is it possible to use eval-when instead? I have tried this,
with the meta package, but have not had any success:

(eval-when (:compile-toplevel :load-toplevel :execute)
(setf *readtable* *meta-readtable*))

--- or something like that.

--
Raymond Wiker Mail: Raymon...@fast.no
Senior Software Engineer Web: http://www.fast.no/
Fast Search & Transfer ASA Phone: +47 23 01 11 60
P.O. Box 1677 Vika Fax: +47 35 54 87 99
NO-0120 Oslo, NORWAY Mob: +47 48 01 11 60

Try FAST Search: http://alltheweb.com/

Hannah Schroeter

unread,
Nov 19, 2002, 8:55:33 AM11/19/02
to
Hello!

Marco Antoniotti <mar...@cs.nyu.edu> wrote:

>[...]

>Of course all of this does not quite answer your question. IMHO what
>has happened is that CLers know that macro charcaters are to be used
>sparingly, therefore, no major clashes have happened in the past in
>mixing and matching separate libraries.

Another convention would be that your package doesn't automatically
modify the readtable referenced from *readtable* at all, but provides
a function to install the specific things.

I.e. you can do things like
(let ((*readtable* *readtable*))
(foo-package:setup-reader-macros)
(load ...)) ; or (read-from-string ...) or ...

Kind regards,

Hannah.

Marco Antoniotti

unread,
Nov 19, 2002, 10:02:56 AM11/19/02
to

Raymond Wiker <Raymon...@fast.no> writes:

> Marco Antoniotti <mar...@cs.nyu.edu> writes:
>
> > RENAME-PACKAGE does not apply in this case. The "space" of macro
> > characters is the read table, and there are no provisions to change it
> > at read time, short of doing
> >
> > #.(setf *readtable* my-readtable)
> >
> > (which - of course - is affected by *READ-EVAL*).
>
> Is it possible to use eval-when instead? I have tried this,
> with the meta package, but have not had any success:
>
> (eval-when (:compile-toplevel :load-toplevel :execute)
> (setf *readtable* *meta-readtable*))

The above should work. As a matter of fact it works in my usage of
the META package.

Marco Antoniotti

unread,
Nov 19, 2002, 10:05:23 AM11/19/02
to

han...@schlund.de (Hannah Schroeter) writes:

Yep. That is what I meant when I was referring to "circumscribed use
of language extensions". I.e. you would have a LOAD-XXX function that
set up the approrpiate read table as you show.

Kalle Olavi Niemitalo

unread,
Nov 19, 2002, 2:01:28 PM11/19/02
to
han...@schlund.de (Hannah Schroeter) writes:

> I.e. you can do things like
> (let ((*readtable* *readtable*))
> (foo-package:setup-reader-macros)
> (load ...)) ; or (read-from-string ...) or ...

I guess this needs a copy-readtable call either in the LET, or in
foo-package:setup-reader-macros. Which place is better?

Erik Naggum

unread,
Nov 19, 2002, 4:34:54 PM11/19/02
to
* Raymond Wiker <Raymon...@fast.no>

| Is it possible to use eval-when instead? I have tried this,
| with the meta package, but have not had any success:
|
| (eval-when (:compile-toplevel :load-toplevel :execute)
| (setf *readtable* *meta-readtable*))

Allegro CL offers a convenient way to access readtables via the named
readtables features. The obvious macro `in-syntax´ then takes a symbol
as argument and assigns the corresponding readtable to *readtable*.

--
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.

Hannah Schroeter

unread,
Nov 20, 2002, 2:09:04 PM11/20/02
to
Hello!

Perhaps more the let, as it is the place which "means" the save of
the readtable.

How about this:

(defmacro with-saved-readtable (&body body)
`(let ((*readtable* (copy-readtable *readtable*)))
,@body))

Kind regards,

Hannah.

Raymond Wiker

unread,
Nov 20, 2002, 4:08:30 PM11/20/02
to
han...@schlund.de (Hannah Schroeter) writes:

> (defmacro with-saved-readtable (&body body)
> `(let ((*readtable* (copy-readtable *readtable*)))
> ,@body))

Note that this is not necessary if "body" is just a call to
load or compile-file.

Hannah Schroeter

unread,
Nov 20, 2002, 4:22:02 PM11/20/02
to
Hello!

Raymond Wiker <Raymon...@fast.no> wrote:
>han...@schlund.de (Hannah Schroeter) writes:

>> (defmacro with-saved-readtable (&body body)
>> `(let ((*readtable* (copy-readtable *readtable*)))
>> ,@body))

> Note that this is not necessary if "body" is just a call to
>load or compile-file.

But

(with-saved-readtable
(setup-alternative-read-syntax)
;; "foo" relies on the alternative read syntax
(load "foo")
;; "bar" also
(compile-file "bar"))

Kind regards,

Hannah.

0 new messages