From: Kenneth Tilton
Subject: Road to Special Enlightenment Survey
Date: 
Message-ID: <49a31e40$0$20301$607ed4bc@cv.net>
Raise your hand if you learned how specials work when some other Lisper 
straightened you out after seeing this code of yours:

   (let ((save *grafport*))
       (setf *grafport* myport)
       (..some grafporting code..)
       (setf *grafport* save))

...with this:

   (let ((*grafport* myport))
      (..some grafporting code..))

If so, how much Lisp had you written by then?

Raise your other hand if you just found out.

kenny

ps. My survey response
*raises hand*
A /lot/.
*still down*

From: Tim Bradshaw
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <cb2622a4-4bb5-4a2f-ab61-c8fef78181c2@f3g2000yqf.googlegroups.com>
On Feb 23, 10:08 pm, Kenneth Tilton <·········@gmail.com> wrote:
> Raise your hand if you learned how specials work when some other Lisper
> straightened you out after seeing this code of yours:
>
>    (let ((save *grafport*))
>        (setf *grafport* myport)
>        (..some grafporting code..)
>        (setf *grafport* save))
>
> ...with this:
>
>    (let ((*grafport* myport))
>       (..some grafporting code..))
>
>

Now raise your third hand if you understand why it might sometimes be
useful to replace the latter code with (code like) the former.  No one
who has used Lisp for more than 10 years is allowed to respond (or at
least to give an explanation).

--tim
From: Scott
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <c61f5012-92da-41ee-abde-7479825709f7@v13g2000yqm.googlegroups.com>
On Feb 23, 4:34 pm, Tim Bradshaw <··········@tfeb.org> wrote:
>
> Now raise your third hand if you understand why it might sometimes be
> useful to replace the latter code with (code like) the former.  No one
> who has used Lisp for more than 10 years is allowed to respond (or at
> least to give an explanation).
>

Maybe you want your change to survive an exception?  That's probably
not what you had in mind.

Ok, how about - let won't work if you just want to modify a piece of
your dynamic variable?

  (let (((aref *a* 1) "foo")) ... )

Probably not that either.
From: Tim Bradshaw
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <1bf3be00-5ce3-43de-b8eb-b32941a17a17@m40g2000yqh.googlegroups.com>
On Feb 24, 3:09 am, Scott <·······@gmail.com> wrote:

> Maybe you want your change to survive an exception?  That's probably
> not what you had in mind.

No, but actually it does bring to mind that Kenny's example is buggy:
what happens when you do:

(let ((x *foo*))
  (setf *foo* ...)
  ...
  (error ...)
  (setf *foo x))

You need an unwind-protect in there, of course.

As a gratuitous hint, my example could never matter in completely
portable CL.
From: Alessio Stalla
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <7a18504b-4b75-4bcd-89b2-966f002d3c96@s24g2000vbp.googlegroups.com>
On Feb 24, 11:04 am, Tim Bradshaw <··········@tfeb.org> wrote:
> On Feb 24, 3:09 am, Scott <·······@gmail.com> wrote:
>
> > Maybe you want your change to survive an exception?  That's probably
> > not what you had in mind.
>
> No, but actually it does bring to mind that Kenny's example is buggy:
> what happens when you do:
>
> (let ((x *foo*))
>   (setf *foo* ...)
>   ...
>   (error ...)
>   (setf *foo x))
>
> You need an unwind-protect in there, of course.
>
> As a gratuitous hint, my example could never matter in completely
> portable CL.

5 or so years of (absolutely not constant) hobbyist level Lisp here...

The hint makes me suspect it has something to do with multithreaded
code. Special bindings in fact usually have "special" behavior wrt
threads...
I can't go further than that, though, since the setf-based code if
anything is *less* thread-safe than the rebinding-based code, which in
most (all?) multithreaded Lisps would do the Right Thing (estabilish a
per-thread binding). Perhaps it would make sense if you actually
wanted to share your new *grafport* across more than you thread for a
while... but I don't think this is what you were thinking about.

So, I'll wait for someone else to give me enlightment :)

Alessio
From: Tim Bradshaw
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <7641cf5c-f8ea-4281-a067-6c9b41d253a7@l1g2000yqj.googlegroups.com>
On Feb 24, 4:13 pm, Alessio Stalla <·············@gmail.com> wrote:
> On Feb 24, 11:04 am, Tim Bradshaw <··········@tfeb.org> wrote:
>
>
>
> > On Feb 24, 3:09 am, Scott <·······@gmail.com> wrote:
>
> > > Maybe you want your change to survive an exception?  That's probably
> > > not what you had in mind.
>
> > No, but actually it does bring to mind that Kenny's example is buggy:
> > what happens when you do:
>
> > (let ((x *foo*))
> >   (setf *foo* ...)
> >   ...
> >   (error ...)
> >   (setf *foo x))
>
> > You need an unwind-protect in there, of course.
>
> > As a gratuitous hint, my example could never matter in completely
> > portable CL.
>
> 5 or so years of (absolutely not constant) hobbyist level Lisp here...
>
> The hint makes me suspect it has something to do with multithreaded
> code. Special bindings in fact usually have "special" behavior wrt
> threads...
> I can't go further than that, though, since the setf-based code if
> anything is *less* thread-safe than the rebinding-based code, which in
> most (all?) multithreaded Lisps would do the Right Thing (estabilish a
> per-thread binding). Perhaps it would make sense if you actually
> wanted to share your new *grafport* across more than you thread for a
> while... but I don't think this is what you were thinking about.

It is - I think all implementations I've used do the right thing with
special bindings - make them thread-local in other words, but
sometimes you want the value change to be global.  Of course, you need
to be careful about synchronisation issues.
From: Tobias C. Rittweiler
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <87ocwrevdh.fsf@freebits.de>
Tim Bradshaw <...> writes:

> >
> > � �(let ((save *grafport*))
> > � � � �(setf *grafport* myport)
> > � � � �(..some grafporting code..)
> > � � � �(setf *grafport* save))
> >
> > ...with this:
> >
> > � �(let ((*grafport* myport))
> > � � � (..some grafporting code..))
> >
> >
>
> Now raise your third hand if you understand why it might sometimes be
> useful to replace the latter code with (code like) the former.  No one
> who has used Lisp for more than 10 years is allowed to respond (or at
> least to give an explanation).

The first one (with an appropriate UNWIND-PROTECT) is LET-GLOBALLY, it
updates the global value slot of a dynamic variable; i.e. the value
update is visible to all existing threads, and threads created within
that extent.

I'd really like to see an actual use case of this though. Can you give
one off-hand?

  -T.
From: Tim Bradshaw
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <1cfe0c79-f9cb-40d2-9106-019c9266d30f@x10g2000yqk.googlegroups.com>
On Feb 24, 2:56 pm, "Tobias C. Rittweiler" <····@freebits.de.invalid>
wrote:

> The first one (with an appropriate UNWIND-PROTECT) is LET-GLOBALLY, it
> updates the global value slot of a dynamic variable; i.e. the value
> update is visible to all existing threads, and threads created within
> that extent.
>

Right answer.

> I'd really like to see an actual use case of this though. Can you give
> one off-hand?
>

I've used it to do things like conrtol readtable variables where the
actual READ happened in a different thread.  Obviously you have to
synchronise properly.
From: Tobias C. Rittweiler
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <87mycazl7p.fsf@freebits.de>
Tim Bradshaw <...> writes:

> > I'd really like to see an actual use case of this though. Can you
> > give one off-hand?
> >
>
> I've used it [LET-GLOBALLY] to do things like conrtol readtable
> variables where the actual READ happened in a different thread.
> Obviously you have to synchronise properly.

Did the actual READ happen in a different thread created within the
extent of the LET-GLOBALLY, or another thread entirely?

If the former, it would seem to me that it's a better choice to make the
dynamic environment explicit that the thread is supposed to run
in. E.g. by the emulating dynamic-closures trick (explicit specification
of dynamic variables to be closed over + PROGV in the thunk.)

  -T.
From: Tobias C. Rittweiler
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <87k57fev3b.fsf@freebits.de>
Me wrote:

> The first one (with an appropriate UNWIND-PROTECT) is LET-GLOBALLY, it
> updates the global value slot of a dynamic variable; i.e. the value
> update is visible to all existing threads, and threads created within
> that extent.

(Visible unless shadowed by thread-local binding, of course.)

  -T.
From: Dimiter "malkia" Stanev
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <gnvmc6$io1$1@malkia.motzarella.org>
Kenneth Tilton wrote:
> Raise your hand if you learned how specials work when some other Lisper 
> straightened you out after seeing this code of yours:
> 
>   (let ((save *grafport*))
>       (setf *grafport* myport)
>       (..some grafporting code..)
>       (setf *grafport* save))
> 
> ....with this:
> 
>   (let ((*grafport* myport))
>      (..some grafporting code..))
> 
> If so, how much Lisp had you written by then?
> 
> Raise your other hand if you just found out.
> 
> kenny
> 
> ps. My survey response
> *raises hand*
> A /lot/.
> *still down*

That one feature is one thing that I really love about Common Lisp. 
Being a tools C++ programmer by day, I miss the trick in C++ - Kaz, 
Pascal and others showed couple of solutions for it (in C++) but it 
wasn't nothing as the original beauty itself.

If that feature, was more common in other language, I betcha people 
wouldn't have to write tons of global variables, or even worse tons of 
variables to the functions being called, and even worse setenv/getenv 
style of programming (I did such two hacks for my current projects, 
because first these we across DLL's calls, and wasn't good idea to 
introduce global variable).

Yes everything is possible in any language, but most of the time you use 
the default paradigm(s) from it.

Only if you have been writing tons of GCC .C code, then you might be 
enlightend.... or not....
From: ··················@gmail.com
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <4e85134e-e2c6-4476-b467-b195294b33dc@d32g2000yqe.googlegroups.com>
On Feb 23, 5:08 pm, Kenneth Tilton <·········@gmail.com> wrote:
> Raise your hand if you learned how specials work when some other Lisper
> straightened you out after seeing this code of yours:
>
>    (let ((save *grafport*))
>        (setf *grafport* myport)
>        (..some grafporting code..)
>        (setf *grafport* save))
>
> ...with this:
>
>    (let ((*grafport* myport))
>       (..some grafporting code..))
>
> If so, how much Lisp had you written by then?
>
> Raise your other hand if you just found out.
>
> kenny
>
> ps. My survey response
> *raises hand*
> A /lot/.
> *still down*

 I learned it after about a month, then forgot, then learned it again,
then forgot,  then.... What were we talking about?

> Now raise your third hand if you understand why it might sometimes be
> useful to replace the latter code with (code like) the former.  No one
> who has used Lisp for more than 10 years is allowed to respond (or at
> least to give an explanation).
> --tim

Maybe I want to modify 'myport' and compare it to 'save'?

In the second example the original *grafport* is inaccessible for the
duration of the let.

You might want to make some changes, do some test, and either
'reset' (setf *grafport* save) or keep going.

I guess also you could have 'save' up above in a let or something, and
then you could treat 'save' as if it were a dynamic variable (ie, bind
it to graphport, have it automagically bind back to whatever it had
been after the let).

This doesn't seem very much like enlightenment, so perhaps I'm too
obtuse to see the real answer.
From: Pascal Costanza
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <70il0gF8o3rpU1@mid.individual.net>
··················@gmail.com wrote:
> On Feb 23, 5:08 pm, Kenneth Tilton <·········@gmail.com> wrote:
>> Raise your hand if you learned how specials work when some other Lisper
>> straightened you out after seeing this code of yours:
>>
>>    (let ((save *grafport*))
>>        (setf *grafport* myport)
>>        (..some grafporting code..)
>>        (setf *grafport* save))
>>
>> ...with this:
>>
>>    (let ((*grafport* myport))
>>       (..some grafporting code..))
>>
>> If so, how much Lisp had you written by then?
>>
>> Raise your other hand if you just found out.
>>
>> kenny
>>
>> ps. My survey response
>> *raises hand*
>> A /lot/.
>> *still down*
> 
>  I learned it after about a month, then forgot, then learned it again,
> then forgot,  then.... What were we talking about?
> 
>> Now raise your third hand if you understand why it might sometimes be
>> useful to replace the latter code with (code like) the former.  No one
>> who has used Lisp for more than 10 years is allowed to respond (or at
>> least to give an explanation).
>> --tim
> 
> Maybe I want to modify 'myport' and compare it to 'save'?
> 
> In the second example the original *grafport* is inaccessible for the
> duration of the let.

There are ways to make it accessible (in portable code).


Pascal

-- 
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Tobias C. Rittweiler
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <87d4d7ep7g.fsf@freebits.de>
Pascal Costanza <...> writes:

> ··················@gmail.com wrote:
>
> > In the second example the original *grafport* is inaccessible for
> > the duration of the let.
>
> There are ways to make it accessible (in portable code).

You mean to get at the global symbol-value slot? How?

  -T.
From: Pascal Costanza
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <70j6jsF9m942U1@mid.individual.net>
Tobias C. Rittweiler wrote:
> Pascal Costanza <...> writes:
> 
>> ··················@gmail.com wrote:
>>
>>> In the second example the original *grafport* is inaccessible for
>>> the duration of the let.
>> There are ways to make it accessible (in portable code).
> 
> You mean to get at the global symbol-value slot? How?

Consider it a puzzle to solve. ;)


Pascal

-- 
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal Costanza
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <70ncsaFg5p4aU2@mid.individual.net>
Pascal Costanza wrote:
> Tobias C. Rittweiler wrote:
>> Pascal Costanza <...> writes:
>>
>>> ··················@gmail.com wrote:
>>>
>>>> In the second example the original *grafport* is inaccessible for
>>>> the duration of the let.
>>> There are ways to make it accessible (in portable code).
>>
>> You mean to get at the global symbol-value slot? How?
> 
> Consider it a puzzle to solve. ;)

Consider:

(defvar *var* (list 42))

(let ((*var* (cons 54 *var*)))
   ;; current value is (car *var*)
   ;; previous values are in (cdr *var*)
   )

The trick is to abstract away from this using symbol macros.


Pascal

-- 
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Tobias C. Rittweiler
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <87hc2h1cdh.fsf@freebits.de>
Pascal Costanza <...> writes:

> Pascal Costanza wrote:
> > Tobias C. Rittweiler wrote:
> > > Pascal Costanza <...> writes:
> > >
> > > > There are ways to make it accessible (in portable code).
> > >
> > > You mean to get at the global symbol-value slot? How?
> >
> > Consider it a puzzle to solve. ;)
>
> Consider:
>
> (defvar *var* (list 42))
>
> (let ((*var* (cons 54 *var*)))
>   ;; current value is (car *var*)
>   ;; previous values are in (cdr *var*)
>   )

Ah, well. I thought you were speaking of a direct way---without the
bookkeeping. Notice that you cannot set the global slot this way.


> The trick is to abstract away from this using symbol macros.

But document so in your documentation! Symbol macros are not fully
interchangeable with real bindings. For example, SPECIAL and
DYNAMIC-EXTENT declarations are verboten on them.

If it mattered, you could probably just introduce another special
variable in this case which contains the binding stack, i.e.

  (let* ((*VAR* 54)
         (*BINDING-STACK+VAR* (cons *VAR* *BINDING-STACK+VAR*)))
    ...)

Possibly putting *BINDING-STACK+VAR* on the symbol-plist of *VAR* if you
have to maintain several such variables.

  -T.
From: Tobias C. Rittweiler
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <87d4d51c5n.fsf@freebits.de>
"Tobias C. Rittweiler" <...> writes:

> Pascal Costanza <...> writes:
>
> > Consider:
> >
> > (defvar *var* (list 42))
> >
> > (let ((*var* (cons 54 *var*)))
> >   ;; current value is (car *var*)
> >   ;; previous values are in (cdr *var*)
> >   )
>
> Ah, well. I thought you were speaking of a direct way---without the
> bookkeeping. Notice that you cannot set the global slot this way.

Err, silly me, of course you can.

  -T.
From: Kaz Kylheku
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <20090303201342.193@gmail.com>
On 2009-02-24, ··················@gmail.com <··················@gmail.com> wrote:
> On Feb 23, 5:08 pm, Kenneth Tilton <·········@gmail.com> wrote:
>> Raise your hand if you learned how specials work when some other Lisper
>> straightened you out after seeing this code of yours:
>>
>>    (let ((save *grafport*))
>>        (setf *grafport* myport)
>>        (..some grafporting code..)
>>        (setf *grafport* save))
>>
>> ...with this:
>>
>>    (let ((*grafport* myport))
>>       (..some grafporting code..))

[ snip ]

>> Now raise your third hand if you understand why it might sometimes be
>> useful to replace the latter code with (code like) the former.  No one
>> who has used Lisp for more than 10 years is allowed to respond (or at
>> least to give an explanation).
>> --tim
>
> Maybe I want to modify 'myport' and compare it to 'save'?
>
> In the second example the original *grafport* is inaccessible for the
> duration of the let.

You still should not (just) use SETF to override the value of a dynamic
variable, like in the first example.  

The ``some grafporting code'' could terminate by a non-local control transfer, in which case you won't execute the restoring code.

UNWIND-PROTECT can fix that, but that still leaves the problem that the code is
not thread safe. Real dynamic variables are not necessarily implemented by
naive saving and restoring of a global place.

What you can do is this:

  (let ((outer-grafport *grafport*)
        (*grafport* new-port))
   ...)

Remember, the init forms in a LET are in the surrounding scope; they do not see
the bindings of the LET itself.

Now you have the original *GRAFPORT* available in a lexical variable,
and a local dynamic binding you can mess with. 

If you just want to make a local binding without changing the value,
then rebind to the same value:

  (let ((outer-grafport *grafport*)
        (*grafport* *grafport*))
   ...)
From: Rob Warnock
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <yq6dncJPKq7Q7D7UnZ2dnUVZ_qzinZ2d@speakeasy.net>
Kenneth Tilton  <·········@gmail.com> wrote:
+---------------
| Raise your hand if you learned how specials work when some other Lisper 
| straightened you out after seeing this code of yours:
| 
|    (let ((save *grafport*))
|        (setf *grafport* myport)
|        (..some grafporting code..)
|        (setf *grafport* save))
| 
| ...with this:
| 
|    (let ((*grafport* myport))
|       (..some grafporting code..))
| 
| If so, how much Lisp had you written by then?
| 
| Raise your other hand if you just found out.
+---------------

For even more extra credit(?!?), raise your third hand if you
already knew about the second form above but just now found out
that you can do the same thing this way:

    (defun do-some-grafporting-thingy (&optional (*grafport* *grafport*))
      ...some grafporting code...)

    ...
    (do-some-grafporting-thingy)	; Uses current value of *GRAFPORT*
    ...
    (do-some-grafporting-thingy myport)	; Temp binds *GRAFPORT* to MYPORT
    ...


-Rob

p.s. A very common usage of that is this idiom:

    (defun format-val (val &key ((stream *standard-output*) *standard-output*))
      (format t "...{magic format for a VAL}..." val))

followed by:

    (format-val some-val)	; goes to *standard-output*
or:
    (format-val some-val :stream some-other-stream-entirely)

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Zach Beane
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <m3prh8q62w.fsf@unnamed.xach.com>
····@rpw3.org (Rob Warnock) writes:

> p.s. A very common usage of that is this idiom:
>
>     (defun format-val (val &key ((stream *standard-output*) *standard-output*))
>       (format t "...{magic format for a VAL}..." val))
>
> followed by:
>
>     (format-val some-val)	; goes to *standard-output*
> or:
>     (format-val some-val :stream some-other-stream-entirely)

I think you mean:

  (format-val some-val 'stream some-other-stream-entirely)

or:

  (defun format-val (val &key ((:stream *standard-output*) *standard-output*))
    ...)

I used that idiom about a zillion times for ZS3 functions to optionally
allow explicit passing of Amazon
credentials. http://xach.com/lisp/zs3/#credentials has the details.

Zach
From: Rob Warnock
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <t5Sdnfj5D-C8hDjUnZ2dnUVZ_jyWnZ2d@speakeasy.net>
Zach Beane  <····@xach.com> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) writes:
| 
| > p.s. A very common usage of that is this idiom:
| >
| >     (defun format-val (val &key
| >                        ((stream *standard-output*) *standard-output*))
| >       (format t "...{magic format for a VAL}..." val))
| >
| > followed by:
| >
| >     (format-val some-val)	; goes to *standard-output*
| > or:
| >     (format-val some-val :stream some-other-stream-entirely)
| 
| I think you mean:
| 
|   (format-val some-val 'stream some-other-stream-entirely)
| 
| or:
| 
|   (defun format-val (val &key ((:stream *standard-output*) *standard-output*))
|     ...)
+---------------

Oops!! Yes, thanks! Right you are! (*blush*) I meant the latter,
of course. I forgot that the coercion to the KEYWORD package doesn't
occur if the ((KEYWORD-NAME VAR) INIT-FORM) is used, only for the
(VAR INIT-FORM) style.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Alessio Stalla
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <ae8538b2-06e0-4874-bbd2-126f282174ac@s36g2000vbp.googlegroups.com>
On Feb 24, 5:02 am, ····@rpw3.org (Rob Warnock) wrote:
> Kenneth Tilton  <·········@gmail.com> wrote:
> +---------------
> | Raise your hand if you learned how specials work when some other Lisper
> | straightened you out after seeing this code of yours:
> |
> |    (let ((save *grafport*))
> |        (setf *grafport* myport)
> |        (..some grafporting code..)
> |        (setf *grafport* save))
> |
> | ...with this:
> |
> |    (let ((*grafport* myport))
> |       (..some grafporting code..))
> |
> | If so, how much Lisp had you written by then?
> |
> | Raise your other hand if you just found out.
> +---------------
>
> For even more extra credit(?!?), raise your third hand if you
> already knew about the second form above but just now found out
> that you can do the same thing this way:
>
>     (defun do-some-grafporting-thingy (&optional (*grafport* *grafport*))
>       ...some grafporting code...)
>
>     ...
>     (do-some-grafporting-thingy)        ; Uses current value of *GRAFPORT*
>     ...
>     (do-some-grafporting-thingy myport) ; Temp binds *GRAFPORT* to MYPORT
>     ...
>
> -Rob
>
> p.s. A very common usage of that is this idiom:
>
>     (defun format-val (val &key ((stream *standard-output*) *standard-output*))
>       (format t "...{magic format for a VAL}..." val))
>
> followed by:
>
>     (format-val some-val)       ; goes to *standard-output*
> or:
>     (format-val some-val :stream some-other-stream-entirely)
>
> -----
> Rob Warnock                     <····@rpw3.org>
> 627 26th Avenue                 <URL:http://rpw3.org/>
> San Mateo, CA 94403             (650)572-2607

Funny... some time ago I asked on this group if the behaviour you
presented here was legal or not... and found out it's perfectly legal
(of course)... and I'm using it since then! Does that count as a third
hand? ;)

Alessio Stalla
From: Andy Chambers
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <b8035e61-43f5-4590-892c-6cdef05a9849@g38g2000yqd.googlegroups.com>
On Feb 23, 10:08 pm, Kenneth Tilton <·········@gmail.com> wrote:
> Raise your hand if you learned how specials work when some other Lisper
> straightened you out after seeing this code of yours:
>
>    (let ((save *grafport*))
>        (setf *grafport* myport)
>        (..some grafporting code..)
>        (setf *grafport* save))
>
> ...with this:
>
>    (let ((*grafport* myport))
>       (..some grafporting code..))

I read it here....

http://www.gigamonkeys.com/book/variables.html#dynamic-aka-special-variables

--
Andy
From: J Kenneth King
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <87k57fu6qz.fsf@agentultra.com>
Andy Chambers <··············@googlemail.com> writes:

> On Feb 23, 10:08 pm, Kenneth Tilton <·········@gmail.com> wrote:
>> Raise your hand if you learned how specials work when some other Lisper
>> straightened you out after seeing this code of yours:
>>
>>    (let ((save *grafport*))
>>        (setf *grafport* myport)
>>        (..some grafporting code..)
>>        (setf *grafport* save))
>>
>> ...with this:
>>
>>    (let ((*grafport* myport))
>>       (..some grafporting code..))
>
> I read it here....
>
> http://www.gigamonkeys.com/book/variables.html#dynamic-aka-special-variables
>
> --
> Andy

Myself as well
From: Kenneth Tilton
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <49a43587$0$5900$607ed4bc@cv.net>
Andy Chambers wrote:
> On Feb 23, 10:08 pm, Kenneth Tilton <·········@gmail.com> wrote:
>> Raise your hand if you learned how specials work when some other Lisper
>> straightened you out after seeing this code of yours:
>>
>>    (let ((save *grafport*))
>>        (setf *grafport* myport)
>>        (..some grafporting code..)
>>        (setf *grafport* save))
>>
>> ...with this:
>>
>>    (let ((*grafport* myport))
>>       (..some grafporting code..))
> 
> I read it here....
> 
> http://www.gigamonkeys.com/book/variables.html#dynamic-aka-special-variables
> 

Puh-lease. You are being responsive to the survey without attempting to 
show off or make someone else feel bad.

What part of c.l.l do you not understand?

<sigh>

kenneth
From: Raffael Cavallaro
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <f2487604-0f9e-4436-bb55-5fb969cfb2f2@f17g2000vbf.googlegroups.com>
On Feb 24, 12:59 pm, Kenneth Tilton <·········@gmail.com> wrote:

> Puh-lease. You are being responsive to the survey without attempting to
> show off or make someone else feel bad.
>
> What part of c.l.l do you not understand?

Oh, mine is worse still. Not only am I not showing off, it was
downright embarrassing.

A while after first buying MCL I sent a question to the mailing list
using the (busted) (setf *foo*... idiom.

When the answer came back (I think from Alice Hartley) my question had
been answered, but the (setf *foo* part of my example code had been
silently replaced with (let ((*foo* ...
<blush>
From: Didier Verna
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <muxskm4mdu3.fsf@uzeb.lrde.epita.fr>
Kenneth Tilton <·········@gmail.com> wrote:

> ps. My survey response
> *raises hand*
> A /lot/.
> *still down*

<xah>
  I guess if your first Lisp dialect is elisp, you learn that on your
  first day.
</xah>

-- 
European Lisp Symposium, May 2009: http://www.european-lisp-symposium.org

Scientific site:   http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com

EPITA/LRDE, 14-16 rue Voltaire, 94276 Le Kremlin-Bic�tre, France
Tel. +33 (0)1 44 08 01 85       Fax. +33 (0)1 53 14 59 22
From: Thomas F. Burdick
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <28d39b1e-8c84-4b9d-b5a5-4f7f8b0ca414@l38g2000vba.googlegroups.com>
On Feb 24, 9:36 am, Didier Verna <······@lrde.epita.fr> wrote:
> Kenneth Tilton <·········@gmail.com> wrote:
> > ps. My survey response
> > *raises hand*
> > A /lot/.
> > *still down*
>
> <xah>
>   I guess if your first Lisp dialect is elisp, you learn that on your
>   first day.
> </xah>

Yeah, my thought, too. Not sure if your <xah> tag was to affiliate
yourself with that statement or disassociate yourself from it -- but
having learned a bit of elisp first, for me it was day 1.
From: Didier Verna
Subject: Re: Road to Special Enlightenment Survey
Date: 
Message-ID: <muxr61nq1jj.fsf@uzeb.lrde.epita.fr>
"Thomas F. Burdick" <········@gmail.com> wrote:

>> <xah>
>> � I guess if your first Lisp dialect is elisp, you learn that on your
>> � first day.
>> </xah>
>
> Yeah, my thought, too. Not sure if your <xah> tag was to affiliate
> yourself with that statement or disassociate yourself from it -- but
> having learned a bit of elisp first, for me it was day 1.

  Affiliate (picture that !) :-)

-- 
European Lisp Symposium, May 2009: http://www.european-lisp-symposium.org
European Lisp Workshop, July 2009: http://elw.bknr.net/2009

Scientific site:   http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com