From: Erik R.
Subject: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <1187962605.593315.244160@q5g2000prf.googlegroups.com>
Greetings all.  I'm writing a simple min-max search program to
practice my lisp.  I need 3 or 4 variables to represent the current
state and then a few functions to change state and get possible future
states.  My background is in java, so my first instinct was to make a
CLOS object with slots and methods.  This quickly turned into a mess
with every method starting with with-slots to make all the slot
variables local and accessible.  I'm certain that this is a horribly
disgusting approach in lisp and I was wondering what the proper way to
go about this is.

Do I just defvar all my state variables?  It seems disgusting to make
them all global like that when I really only want to access them from
a handful of methods.

Do I surround my functions with a let that defines the variables?

A defstruct that I pass as a parameter to all my functions?

I'm sure this is a really silly newbie question, but it's just not
obvious, and none of the lisp books I've read address stuff like this.

Cheers,
Erik

From: patzy
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <1187966118.267485.305700@m37g2000prh.googlegroups.com>
On Aug 24, 3:36 pm, "Erik R." <·············@gmail.com> wrote:
> Greetings all.  I'm writing a simple min-max search program to
> practice my lisp.  I need 3 or 4 variables to represent the current
> state and then a few functions to change state and get possible future
> states.  My background is in java, so my first instinct was to make a
> CLOS object with slots and methods.  This quickly turned into a mess
> with every method starting with with-slots to make all the slot
> variables local and accessible.  I'm certain that this is a horribly
> disgusting approach in lisp and I was wondering what the proper way to
> go about this is.
>
> Do I just defvar all my state variables?  It seems disgusting to make
> them all global like that when I really only want to access them from
> a handful of methods.
>
> Do I surround my functions with a let that defines the variables?
>
> A defstruct that I pass as a parameter to all my functions?
>
> I'm sure this is a really silly newbie question, but it's just not
> obvious, and none of the lisp books I've read address stuff like this.
>
> Cheers,
> Erik

Maybe you should have a look at closures:
http://www.gigamonkeys.com/book/variables.html
http://www.bookshelf.jp/texi/onlisp/onlisp_3.html#SEC18
From: Erik R.
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <1187966847.459317.21180@i13g2000prf.googlegroups.com>
On Aug 24, 4:35 pm, patzy <·············@gmail.com> wrote:
> On Aug 24, 3:36 pm, "Erik R." <·············@gmail.com> wrote:
>
>
>
> > Greetings all.  I'm writing a simple min-max search program to
> > practice my lisp.  I need 3 or 4 variables to represent the current
> > state and then a few functions to change state and get possible future
> > states.  My background is in java, so my first instinct was to make a
> > CLOS object with slots and methods.  This quickly turned into a mess
> > with every method starting with with-slots to make all the slot
> > variables local and accessible.  I'm certain that this is a horribly
> > disgusting approach in lisp and I was wondering what the proper way to
> > go about this is.
>
> > Do I just defvar all my state variables?  It seems disgusting to make
> > them all global like that when I really only want to access them from
> > a handful of methods.
>
> > Do I surround my functions with a let that defines the variables?
>
> > A defstruct that I pass as a parameter to all my functions?
>
> > I'm sure this is a really silly newbie question, but it's just not
> > obvious, and none of the lisp books I've read address stuff like this.
>
> > Cheers,
> > Erik
>
> Maybe you should have a look at closures:http://www.gigamonkeys.com/book/variables.htmlhttp://www.bookshelf.jp/texi/onlisp/onlisp_3.html#SEC18

So I define them in a let around my defuns?
From: Ken Tilton
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <inGzi.54$qH6.20@newsfe12.lga>
Erik R. wrote:
> Greetings all.  I'm writing a simple min-max search program to
> practice my lisp.  I need 3 or 4 variables to represent the current
> state and then a few functions to change state and get possible future
> states.  My background is in java, so my first instinct was to make a
> CLOS object with slots and methods.  This quickly turned into a mess
> with every method starting with with-slots to make all the slot
> variables local and accessible.

You are coming from Java and /anything/ looks like a mess? Methinks Lisp 
has taken hold of you already. Happy thought,

>  I'm certain that this is a horribly
> disgusting approach in lisp and I was wondering what the proper way to
> go about this is.
> 
> Do I just defvar all my state variables?  It seems disgusting to make
> them all global like that when I really only want to access them from
> a handful of methods.

Make up your frickin mind, will you? :) It looks as if you are halfway 
on your Road. Look, you can have it either way, pile them into a struct 
and pass it around or use specials. You can pile them into a struct and 
bind /that/ to one special. You can run around on the street butt naked 
quacking like a duck. This is Lisp, a multi-fetish language. I digress.

If it helps, specials are not your typical filthy globals. They are 
accessible only during the runtime lifetime of their binding, to all the 
code reached during that binding, which is precisely what you want.

> 
> Do I surround my functions with a let that defines the variables?

It just binds them. Hmmm, I guess this could be a place for (declare 
(special *hi-mom*)), but I myself have never played with that.

> 
> A defstruct that I pass as a parameter to all my functions?
> 
> I'm sure this is a really silly newbie question, but it's just not
> obvious, and none of the lisp books I've read address stuff like this.

I think books are hard enough to write. Paul Graham took a nice crack at 
writing a style guide with On Lisp, but he is a rare cat.

hth,kt

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: Frank Goenninger DG1SBG
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <lzlkc0d8og.fsf@pcsde001.de.goenninger.net>
Ken Tilton <···········@optonline.net> writes:

> Make up your frickin mind, will you? :) It looks as if you are halfway
> on your Road. Look, you can have it either way, pile them into a
> struct and pass it around or use specials. You can pile them into a
> struct and bind /that/ to one special. You can run around on the
> street butt naked quacking like a duck. This is Lisp, a multi-fetish
> language. I digress.

Wow - another one to be "fortune-filed" into kenny-fortunes.text ;-)

Frank
-- 

  Frank Goenninger

  frgo(at)mac(dot)com

  "Don't ask me! I haven't been reading comp.lang.lisp long enough to 
  really know ..."
From: Rob St. Amant
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <fancq1$q14$1@blackhelicopter.databasix.com>
"Erik R." <·············@gmail.com> writes:

> Greetings all.  I'm writing a simple min-max search program to
> practice my lisp.  I need 3 or 4 variables to represent the current
> state and then a few functions to change state and get possible future
> states.  My background is in java, so my first instinct was to make a
> CLOS object with slots and methods.  This quickly turned into a mess
> with every method starting with with-slots to make all the slot
> variables local and accessible.  I'm certain that this is a horribly
> disgusting approach in lisp and I was wondering what the proper way to
> go about this is.
>
> Do I just defvar all my state variables?  It seems disgusting to make
> them all global like that when I really only want to access them from
> a handful of methods.
>
> Do I surround my functions with a let that defines the variables?
>
> A defstruct that I pass as a parameter to all my functions?
>
> I'm sure this is a really silly newbie question, but it's just not
> obvious, and none of the lisp books I've read address stuff like this.

I'm not sure how special variables address your problem.  For all but
the simplest search algorithms, you'll need to maintain a potentially
large set of distinct states that you'll be generating and moving
between.  It's reasonable to encapsulate the information about a state
in some way, and structures or class instances are a natural way to do
it.  These get passed to your search algorithm, with relevant
information pulled out by appropriate accessor methods or functions.

In case you haven't checked it out already, Peter Norvig's Paradigms
of AI Programming is a good source for information about Lisp code and
program design for AI problems.  There's an implementation of minimax
search in his Othello game player that you may find helpful.
From: Matthias Buelow
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <5j8ilvF3tdeffU1@mid.dfncis.de>
Erik R. <·············@gmail.com> wrote:

> Do I just defvar all my state variables?  It seems disgusting to make

You can pass the state as argument(s) (if practical) for a more
functional approach... that's what I like doing although many here are
really into setq/setf.

If you're coming from Java, you probably need to unlearn that
"everything-in-the-world-is-an-object" nonsense first.
From: Ken Tilton
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <4fGzi.52$qH6.15@newsfe12.lga>
Matthias Buelow wrote:
> Erik R. <·············@gmail.com> wrote:
> 
> 
>>Do I just defvar all my state variables?  It seems disgusting to make
> 
> 
> You can pass the state as argument(s) (if practical) for a more
> functional approach... that's what I like doing although many here are
> really into setq/setf.

The use case described by the OP is a good one for special variables. 
Those are not as unclean as classic globals. Piling things into argument 
lists is a slippery slope as the code gets more complex and you are 
forever having to add them to arg lists of new functions.

kt

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: Matthias Buelow
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <5j8s8hF3rsp1dU1@mid.dfncis.de>
Ken Tilton <···········@optonline.net> wrote:

> The use case described by the OP is a good one for special variables. 
> Those are not as unclean as classic globals.

Special variables are a poor and obscure alternative to functional
arguments and shouldn't be used in place of them.

> Piling things into argument 
> lists is a slippery slope as the code gets more complex and you are 
> forever having to add them to arg lists of new functions.

What isn't a slippery slope in programming.
From: Erik R.
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <1187992540.025027.113530@x35g2000prf.googlegroups.com>
On Aug 24, 10:09 pm, Matthias Buelow <····@incubus.de> wrote:
> Ken Tilton <···········@optonline.net> wrote:
> > The use case described by the OP is a good one for special variables.
> > Those are not as unclean as classic globals.
>
> Special variables are a poor and obscure alternative to functional
> arguments and shouldn't be used in place of them.
>
> > Piling things into argument
> > lists is a slippery slope as the code gets more complex and you are
> > forever having to add them to arg lists of new functions.
>


> What isn't a slippery slope in programming.

Too true.  Thanks to all of you.  I can see that it's not completely
as clear-cut as I thought.  It depends on how object oriented or how
functional I want to keep things.

Cheers,
Erik
From: Ken Tilton
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <5JKzi.147$qH6.112@newsfe12.lga>
Matthias Buelow wrote:
> Ken Tilton <···········@optonline.net> wrote:
> 
> 
>>The use case described by the OP is a good one for special variables. 
>>Those are not as unclean as classic globals.
> 
> 
> Special variables are a poor and obscure alternative to functional
> arguments and shouldn't be used in place of them.

Mathias, you ignorant slut. If you /can/ use a special variable atop a 
call tree, then there is a helluva of a good chance it is less obscure 
to use a special, and passing the data around as your cherished "pure 
functional" parameters is nothing but an artifice of your enslavement to 
purism. If the info is being passed as an argument, I am being told that 
any given call might be supplied with a different place. If I see a 
special, I understand it will be bound one place and that the call tree 
will be operating on one place (yes, I can do a spiritual interrupt and 
rebind the special in an emergency, but nothing has change: we have 
bound the special one place and an entire call tree is now wailing away 
at it).

Shouldn't you be over at comp.lang.functional?

> 
> 
>>Piling things into argument 
>>lists is a slippery slope as the code gets more complex and you are 
>>forever having to add them to arg lists of new functions.
> 
> 
> What isn't a slippery slope in programming.

Oh, my. You do program don't you? If so, I would hate to see it. I am a 
programming god for one reason: when I sense the slightest drop-off in 
productivity from my latest bit of code, out it comes. I cannot reliably 
write good code, but I can reliably know when it has gotten unpleasant 
to work with my code.

kenny

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: Ken Tilton
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <xRLzi.70$Sm1.56@newsfe12.lga>
Matthias Buelow wrote:
> Ken Tilton <···········@optonline.net> wrote:
> 
> 
>>The use case described by the OP is a good one for special variables. 
>>Those are not as unclean as classic globals.
> 
> 
> Special variables are a poor and obscure alternative to functional
> arguments and shouldn't be used in place of them.

I meant to ask, when /should/ they be used?

kt

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: Rob Warnock
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <2ZednQuvq44EClLbnZ2dnUVZ_v2unZ2d@speakeasy.net>
Ken Tilton  <·········@gmail.com> wrote:
+---------------
| Matthias Buelow wrote:
| > Ken Tilton <···········@optonline.net> wrote:
| >>The use case described by the OP is a good one for special variables. 
| >>Those are not as unclean as classic globals.
| > 
| > Special variables are a poor and obscure alternative to functional
| > arguments and shouldn't be used in place of them.
| 
| I meant to ask, when /should/ they be used?
+---------------

For me, the two classic use cases are:

1. Things that work more-or-less like the ANSI-defined specials
   such as *READ-BASE*, that is, large numbers of miscellaneous
   global parameters that you *usually* want to just leave alone
   but sometimes want to rebind for the dynamic extent of one
   subtree of function calls.

   Thanks *goodness* for specials for this case!! Passing the ~20 (!)
   or so specials that affect the Lisp printer [see CLHS 22.1.1.1]
   around in every function call just to enforce some kind of
   functional "purity" would simply be insane.

2. Things that hold "this request" (or things *about* "this request")
   for request/response protocols, especially when using some kind
   of threading so that there are multiple "this" objects live at
   any one instant. E.g., my personal web infrastructure has a special
   named *HTTP-REQUEST*, a structure of type HTTP-REQUEST (duh!) that
   holds all the gunk related to one -- freshly bound by the thread
   that gets spawned upon each new ACCEPT on port 80. As the request
   goes through the steps of its processing, various additional bits
   of gunk get added to (or deleted from) the HTTP-REQUEST object.
   After responding, the thread dies, and on its way out *HTTP-REQUEST*
   gets unbound and the object gets GC'd, eventually. [No, I don't try
   to re-use them, though I do (sometimes) re-cycle the connections
   they had open to PostgreSQL.]

   Another similar, though non-threaded, case is a discrete
   event simulator, where specials with names like *CURRENT-TIME*,
   *CURRENT-PROCESS*, *CURRENT-EVENT*, *CURRENT-NET*, *CURRENT-
   DRIVER*, etc., may get bound & re-bound by the simulator's
   main event loop [possibly a *very* large number of times
   for one tick of *CURRENT-TIME*!], so that any given instance
   of an object being simulated has a lexically-constant but
   dynamically-varying environment. [Yes, Kenny, such things
   should probably all be re-written in Cells. Humor me.]


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ken Tilton
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <8xSzi.137$az5.103@newsfe12.lga>
Rob Warnock wrote:
> Ken Tilton  <·········@gmail.com> wrote:
> +---------------
> | Matthias Buelow wrote:
> | > Ken Tilton <···········@optonline.net> wrote:
> | >>The use case described by the OP is a good one for special variables. 
> | >>Those are not as unclean as classic globals.
> | > 
> | > Special variables are a poor and obscure alternative to functional
> | > arguments and shouldn't be used in place of them.
> | 
> | I meant to ask, when /should/ they be used?
> +---------------
> 
> For me, the two classic use cases are:
> 
> 1. Things that work more-or-less like the ANSI-defined specials
>    such as *READ-BASE*, that is, large numbers of miscellaneous
>    global parameters that you *usually* want to just leave alone
>    but sometimes want to rebind for the dynamic extent of one
>    subtree of function calls.
> 
>    Thanks *goodness* for specials for this case!! Passing the ~20 (!)
>    or so...

That's a cop-out! The interesting question arises when there is /one/ 
variable to pass around, such as GrafPort in QuickDraw. Can I set it and 
forget it, or do I have to pass it around so FillRect retains its 
functional purity as Matthias demands? The Mac would have lasted about a 
month with him as Chief Software Architect...

I think he must be a refugee from c.l.functional who got fed up with 
functional purity without realizing why.

kt

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: Scott Burson
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <1188024813.299704.252680@z24g2000prh.googlegroups.com>
On Aug 24, 7:44 pm, ····@rpw3.org (Rob Warnock) wrote:
> For me, the two classic use cases [for specials] are:
>
> 1. Things that work more-or-less like the ANSI-defined specials
>    such as *READ-BASE* [...]
>
>    Thank *goodness* for specials for this case!! Passing the ~20 (!)
>    or so specials that affect the Lisp printer [see CLHS 22.1.1.1]
>    around in every function call just to enforce some kind of
>    functional "purity" would simply be insane.

That would be insane, but having a printer class with these specials
turned into instance variables would be quite reasonable.  All you
need is a copy-with-variations method that takes an existing instance
and a bunch of keyword parameters, and returns a new instance that has
been appropriately modified.  If one of its instance variables is the
stream it writes to, then we would pass it around in place of a stream
-- something we are already used to passing around.

Specials are also solving a different problem: that the REPL has
state, and we need a way to access and modify that state.  For this
use I think specials are fine.  But this is a pretty limited use case.

> 2. Things that hold "this request" (or things *about* "this request")
>    for request/response protocols

Here I'd rather pass the object around as an argument.  Just a matter
of taste, I guess.

-- Scott
From: Robert Uhl
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <m31wdrr5dm.fsf@latakia.dyndns.org>
Scott Burson <········@gmail.com> writes:

> On Aug 24, 7:44 pm, ····@rpw3.org (Rob Warnock) wrote:
>> For me, the two classic use cases [for specials] are:
>>
>> 1. Things that work more-or-less like the ANSI-defined specials
>>    such as *READ-BASE* [...]
>>
>>    Thank *goodness* for specials for this case!! Passing the ~20 (!)
>>    or so specials that affect the Lisp printer [see CLHS 22.1.1.1]
>>    around in every function call just to enforce some kind of
>>    functional "purity" would simply be insane.
>
> That would be insane, but having a printer class with these specials
> turned into instance variables would be quite reasonable.

Ah, but if most of the time the defaults are fine, isn't cleaner to just
call (FOO BAR) than (FOO BAR context)?  And of course, one has to
retrieve the context, so really it's the difference between (FOO BAR)
and (FOO BAR (get-FOO-context)).  Or the default context could be a
global variable, probably constant: (FOO BAR +FOO-context+).

> All you need is a copy-with-variations method that takes an existing
> instance and a bunch of keyword parameters, and returns a new instance
> that has been appropriately modified.

So:

  (let ((context (copy-context=with-variations +FOO-context+
                                               :add-1 t
                                               :colour nil)))
       (FOO BAR context))

is cleaner than:

  (let ((*FOO-add-1* t)
        (*FOO-colour nil))
       (FOO BAR))

Perhaps our aesthetic senses are different...

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
Customs officers enter into a Faustian bargain whereby they are given
absolute power in exchange for their sense of humour.  Hitler's dad, you
will remember noddingly, was a Customs officer.  And _Hitler_ thought he
was a nasty piece of work.                              --Mil Millington
From: Scott Burson
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <1188088304.566011.120930@r23g2000prd.googlegroups.com>
On Aug 25, 8:38 am, Robert Uhl <·········@NOSPAMgmail.com> wrote:
> So:
>
>   (let ((context (copy-context=with-variations +FOO-context+
>                                                :add-1 t
>                                                :colour nil)))
>        (FOO BAR context))
>
> is cleaner than:
>
>   (let ((*FOO-add-1* t)
>         (*FOO-colour nil))
>        (FOO BAR))
>
> Perhaps our aesthetic senses are different...

Perhaps they are, and reasonable people certainly can differ about
such things, but let me give some reasons why I lean toward the first
version even though it's a little more verbose:

() The dataflow relationship is explicit.  I know that FOO depends on
the context in some way (and if I look at the body of FOO I can
similarly see immediately which of its callees have the same
dependence).  In the second case, it's not as easy to trace the
dataflow -- well, in this example, the scope of the LET contains only
the call to FOO, but in general LET bodies are not always so simple,
and anyway the same applies to the body of FOO, the bodies of its
callees, etc.

() If I ever need to delay some operation by wrapping it in a lambda
and calling the resulting function later, the first form will behave
predictably and the second won't.

-- Scott
From: Rob Warnock
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <Yc6dnYceUr8zSE3bnZ2dnUVZ_h2pnZ2d@speakeasy.net>
Scott Burson  <········@gmail.com> wrote:
+---------------
| Robert Uhl <·········@NOSPAMgmail.com> wrote:
| > So: (let ((context (copy-context=with-variations +FOO-context+
| >                                                :add-1 t
| >                                                :colour nil)))
| >        (FOO BAR context))
| > is cleaner than:
| >   (let ((*FOO-add-1* t)
| >         (*FOO-colour nil))
| >        (FOO BAR))
...
| () If I ever need to delay some operation by wrapping it in a lambda
| and calling the resulting function later, the first form will behave
| predictably and the second won't.
+---------------

Sure it will, if you wrap the LAMBDA around the binding form too:

    (lambda ()
      (let ((*FOO-add-1* t)
	    (*FOO-colour nil))
        (FOO BAR)))

Or if you're worried about more parameters than those, you could
always do something along these lines [which I confess I have done
on certain rare occasions]:

    (let ((later-add-1 t)
	  (later-colour nil)
	  (later-style *foo-style*)
	  (later-font *foo-font*)
	  (later-weight *foo-weight*))
      (lambda (bar)
	(let ((*foo-add-1* later-add-1)
	      (*foo-colour* later-colour)
	      (*foo-style* later-style)
	      (*foo-font* later-font)
	      (*foo-weight* later-weight))
	  (foo bar))))


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Scott Burson
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <1188098392.529964.81690@r23g2000prd.googlegroups.com>
On Aug 25, 6:21 pm, ····@rpw3.org (Rob Warnock) wrote:
> Scott Burson  <········@gmail.com> wrote:
> +---------------
> | Robert Uhl <·········@NOSPAMgmail.com> wrote:
> | > So: (let ((context (copy-context=with-variations +FOO-context+
> | >                                                :add-1 t
> | >                                                :colour nil)))
> | >        (FOO BAR context))
> | > is cleaner than:
> | >   (let ((*FOO-add-1* t)
> | >         (*FOO-colour nil))
> | >        (FOO BAR))
> ...
> | () If I ever need to delay some operation by wrapping it in a lambda
> | and calling the resulting function later, the first form will behave
> | predictably and the second won't.
> +---------------
>
> Sure it will, if you wrap the LAMBDA around the binding form too:
>
>     (lambda ()
>       (let ((*FOO-add-1* t)
>             (*FOO-colour nil))
>         (FOO BAR)))

I meant, if I needed to lambda-abstract something somewhere in the
guts of FOO -- if the function thus created could be called after FOO
returned, I would have to remember to do something like what you show
below:

> Or if you're worried about more parameters than those, you could
> always do something along these lines [which I confess I have done
> on certain rare occasions]:
>
>     (let ((later-add-1 t)
>           (later-colour nil)
>           (later-style *foo-style*)
>           (later-font *foo-font*)
>           (later-weight *foo-weight*))
>       (lambda (bar)
>         (let ((*foo-add-1* later-add-1)
>               (*foo-colour* later-colour)
>               (*foo-style* later-style)
>               (*foo-font* later-font)
>               (*foo-weight* later-weight))
>           (foo bar))))

I think "confess" is the operative word here :)

Seriously -- if I found myself needing to do this, I would definitely
want to switch to using an instance.

-- Scott
From: Russell McManus
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <87hcmnxi5d.fsf@thelonious.cl-user.org>
Scott Burson <········@gmail.com> writes:

> That would be insane, but having a printer class with these specials
> turned into instance variables would be quite reasonable.  All you
> need is a copy-with-variations method that takes an existing instance
> and a bunch of keyword parameters, and returns a new instance that has
> been appropriately modified.  If one of its instance variables is the
> stream it writes to, then we would pass it around in place of a stream
> -- something we are already used to passing around.

I don't agree.  Assume I want to print things out in hex by default.
I have a function that I call, that in turn calls other functions that
print things out.  The first function doesn't do any printing, and
does not accept a printer context object as argument.  How do I pass
the copied-with-variations print context instance down to the inner
level functions?

-russ
From: Scott Burson
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <1188100247.124358.80400@q5g2000prf.googlegroups.com>
On Aug 25, 5:18 pm, Russell McManus <···············@yahoo.com> wrote:
> Assume I want to print things out in hex by default.
> I have a function that I call, that in turn calls other functions that
> print things out.  The first function doesn't do any printing, and
> does not accept a printer context object as argument.  How do I pass
> the copied-with-variations print context instance down to the inner
> level functions?

I think you've contradicted yourself.  You say the first function
doesn't do any printing, but it calls other functions that do.  Yet
viewed in terms of its contract, either this first function is
supposed to print something or it isn't.  If it is, the fact that it
does so only indirectly, by calling other functions, is irrelevant --
it still has printing as part of its contract, and therefore I don't
have a problem with making it pass around a printer context.

Debugging printout is obviously a different case -- you want your
function to print something, but that's not part of its contract --
and I don't have a problem with using specials interactively to assist
in debugging.

But, you might say, what about a general-purpose higher-order function
like, say, MAPC?  It doesn't already pass around a printer context,
and certainly shouldn't be made to do so.  Right -- and that's exactly
why you want to pass it a closure that knows about the printer context
and whatever else is relevant to that particular MAPC call.

Look, I'm well aware that in the course of exploratory programming or
even normal maintenance, there are situations where adding a special
is a quick solution to a problem; and sometimes expediency is the
important thing.  But in my experience, if you can take the time to
refactor your code, making the piece of information that you wanted to
pass via a special instead be an attribute of some appropriate object,
I believe you will very likely wind up with a higher-quality, more
maintainable piece of code.

-- Scott
From: Russell McManus
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <87d4xaxoo0.fsf@thelonious.cl-user.org>
Scott Burson <········@gmail.com> writes:

> On Aug 25, 5:18 pm, Russell McManus <···············@yahoo.com> wrote:
>> Assume I want to print things out in hex by default.
>> I have a function that I call, that in turn calls other functions that
>> print things out.  The first function doesn't do any printing, and
>> does not accept a printer context object as argument.  How do I pass
>> the copied-with-variations print context instance down to the inner
>> level functions?
>
> I think you've contradicted yourself.  You say the first function
> doesn't do any printing, but it calls other functions that do.  Yet
> viewed in terms of its contract, either this first function is
> supposed to print something or it isn't.  If it is, the fact that it
> does so only indirectly, by calling other functions, is irrelevant --
> it still has printing as part of its contract, and therefore I don't
> have a problem with making it pass around a printer context.

J'ever think that a function might be used in a context not originally
envisioned by it's original author?  I thought not.

-russ
From: Dimiter "malkia" Stanev
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <5jk1ddF3rk12fU1@mid.individual.net>
Special (dynamic) variables are one of the things that got me into Lisp.

I grew tired of supporting an in-house tool (C++), which had to be 
extended with various options, and I've ended up making each function 
taking (..., int argc, char *argv[]) and then each function would parse 
it (a bit of greenspunning).

Then I've put the stuff in global variables, and removed the (..., int 
argc, char *argv[]), but for some reason I needed to change some of the 
things temporarily, and restore them, so I've ended up doing something 
like a stack for each global variable.

And when I started reading lisp I understand the wisdom behind special 
variables, and all my wasted hours behind emulating what's already have 
been done.

That plus the multiple-value returns (Another invention that I needed 
these days in a C++ code to overcome total rewrite of foreign code 
portions in a much larger tool - mainly to avoid massive amounts of 
DLL's to be recompiled).

Rob Warnock wrote:
> Ken Tilton  <·········@gmail.com> wrote:
> +---------------
> | Matthias Buelow wrote:
> | > Ken Tilton <···········@optonline.net> wrote:
> | >>The use case described by the OP is a good one for special variables. 
> | >>Those are not as unclean as classic globals.
> | > 
> | > Special variables are a poor and obscure alternative to functional
> | > arguments and shouldn't be used in place of them.
> | 
> | I meant to ask, when /should/ they be used?
> +---------------
> 
> For me, the two classic use cases are:
> 
> 1. Things that work more-or-less like the ANSI-defined specials
>    such as *READ-BASE*, that is, large numbers of miscellaneous
>    global parameters that you *usually* want to just leave alone
>    but sometimes want to rebind for the dynamic extent of one
>    subtree of function calls.
> 
>    Thanks *goodness* for specials for this case!! Passing the ~20 (!)
>    or so specials that affect the Lisp printer [see CLHS 22.1.1.1]
>    around in every function call just to enforce some kind of
>    functional "purity" would simply be insane.
> 
> 2. Things that hold "this request" (or things *about* "this request")
>    for request/response protocols, especially when using some kind
>    of threading so that there are multiple "this" objects live at
>    any one instant. E.g., my personal web infrastructure has a special
>    named *HTTP-REQUEST*, a structure of type HTTP-REQUEST (duh!) that
>    holds all the gunk related to one -- freshly bound by the thread
>    that gets spawned upon each new ACCEPT on port 80. As the request
>    goes through the steps of its processing, various additional bits
>    of gunk get added to (or deleted from) the HTTP-REQUEST object.
>    After responding, the thread dies, and on its way out *HTTP-REQUEST*
>    gets unbound and the object gets GC'd, eventually. [No, I don't try
>    to re-use them, though I do (sometimes) re-cycle the connections
>    they had open to PostgreSQL.]
> 
>    Another similar, though non-threaded, case is a discrete
>    event simulator, where specials with names like *CURRENT-TIME*,
>    *CURRENT-PROCESS*, *CURRENT-EVENT*, *CURRENT-NET*, *CURRENT-
>    DRIVER*, etc., may get bound & re-bound by the simulator's
>    main event loop [possibly a *very* large number of times
>    for one tick of *CURRENT-TIME*!], so that any given instance
>    of an object being simulated has a lexically-constant but
>    dynamically-varying environment. [Yes, Kenny, such things
>    should probably all be re-written in Cells. Humor me.]
> 
> 
> -Rob
> 
> -----
> Rob Warnock			<····@rpw3.org>
> 627 26th Avenue			<URL:http://rpw3.org/>
> San Mateo, CA 94403		(650)572-2607
> 
From: Ken Tilton
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <9Y5Bi.76$IM6.41@newsfe12.lga>
Dimiter "malkia" Stanev wrote:
> Special (dynamic) variables are one of the things that got me into Lisp.

OK, but you are only allowed by the finger shakers to use them for PRINT.

> 
> I grew tired of supporting an in-house tool (C++), which had to be 
> extended with various options, and I've ended up making each function 
> taking (..., int argc, char *argv[]) and then each function would parse 
> it (a bit of greenspunning).

It occurs to me that the infinitive should be "to greenspin". Certainly 
"So there I am using the C preprocessor to greenspin macros and I hit a 
wall..." is easier to say.

> 
> Then I've put the stuff in global variables, and removed the (..., int 
> argc, char *argv[]), but for some reason I needed to change some of the 
> things temporarily, and restore them, so I've ended up doing something 
> like a stack for each global variable.
> 
> And when I started reading lisp I understand the wisdom behind special 
> variables, and all my wasted hours behind emulating what's already have 
> been done.
> 
> That plus the multiple-value returns (Another invention that I needed 
> these days in a C++ code to overcome total rewrite of foreign code 
> portions in a much larger tool - mainly to avoid massive amounts of 
> DLL's to be recompiled).

You need to read Burdick's Road to Lisp. Then add your own. I think he 
was doing macros in C++.

OK, this NG has become unbearable with the stench of nooby diapers. What 
is the obscure niche language where I will be safe forever? I am 
thinking Forth. Yes? No?

kxo
From: Rob Warnock
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <LM6dndbTfLn1sUjbnZ2dnUVZ_qelnZ2d@speakeasy.net>
Ken Tilton  <·········@gmail.com> wrote:
+---------------
| Dimiter "malkia" Stanev wrote:
| > ...various options, and I've ended up making each function 
| > taking (..., int argc, char *argv[]) and then each function would parse 
| > it (a bit of greenspunning).
| 
| It occurs to me that the infinitive should be "to greenspin". Certainly 
| "So there I am using the C preprocessor to greenspin macros and I hit a 
| wall..." is easier to say.
+---------------

Nah, "to greenspin" is what Ben Bernanke's doing about mortgage rates...
[Hint: Whom did he succeed?]


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: David Combs
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <fd3v43$66t$1@reader1.panix.com>
In article <···············@newsfe12.lga>,
Ken Tilton  <·········@gmail.com> wrote:
>
>
...

>You need to read Burdick's Road to Lisp. ...

...

THANK YOU, KEN!!!!

I googled   Burdick    "road to lisp"

and got what I think was the entire survey, responses, etc.  INCREDIBLE!

How could I not already have known about this?


(Maybe someday someone could massage it into one large
tekinfo or pdf or whatever, for people to print out
and read at leisure (train, "throne room", bed, etc)?

And tell lisp-questioners and berators(sp?) to study it,
and *then* come back. )


Thanks again, ken.

David (lurker)
From: Ken Tilton
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <CYkJi.212$Wm2.152@newsfe12.lga>
David Combs wrote:
> In article <···············@newsfe12.lga>,
> Ken Tilton  <·········@gmail.com> wrote:
> 
>>
> ...
> 
> 
>>You need to read Burdick's Road to Lisp. ...
> 
> 
> ...
> 
> THANK YOU, KEN!!!!
> 
> I googled   Burdick    "road to lisp"
> 
> and got what I think was the entire survey, responses, etc.  INCREDIBLE!
> 
> How could I not already have known about this?

The Yobbos decided to punish me by forcing the survey off Cliki on the 
grounds that it was a commercial product.

Also, no link, no traffic:

    http://wiki.alu.org/The_Road_to_Lisp_Survey

I should check, see if we have any new respondents. You found the 
highlight film, right?

    http://wiki.alu.org/RtL_Highlight_Film

That is always fun to read.

kenny

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: Brian Adkins
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <1190526588.453308.11790@n39g2000hsh.googlegroups.com>
On Sep 22, 11:18 pm, Ken Tilton <···········@optonline.net> wrote:
> The Yobbos decided to punish me by forcing the survey off Cliki on the
> grounds that it was a commercial product.

What's commercial about the survey?
From: Ken Tilton
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <HRsJi.9$Vi4.8@newsfe12.lga>
Brian Adkins wrote:
> On Sep 22, 11:18 pm, Ken Tilton <···········@optonline.net> wrote:
> 
>>The Yobbos decided to punish me by forcing the survey off Cliki on the
>>grounds that it was a commercial product.
> 
> 
> What's commercial about the survey?
> 

Sorry, I collapsed a double-negative. The real reason was that some of 
the people who responded do not produce non-commercial software... Hmmm, 
that still sounds stupid.

To be fair the survey was quite popular in the community so they needed 
a respectable reason and I guess they felt "We hate Kenny" would not do.

Ironically their character assassination campaign has succeeded so well 
that they would look less silly now had they gone with "Omigod! We 
killed Kenny's survey!", but hindsight is always a 20/20 shotgun.

kenny
From: John Thingstad
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <op.ty37xenhpqzri1@pandora.upc.no>
P� Sun, 23 Sep 2007 14:17:34 +0200, skrev Ken Tilton  
<···········@optonline.net>:

> Ironically their character assassination campaign has succeeded so well  
> that they would look less silly now had they gone with "Omigod! We  
> killed Kenny's survey!", but hindsight is always a 20/20 shotgun.
>
> kenny

That exclamation is property of "South Park" and thus a copyright  
violation. ;)
From: ···@telent.net
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <470157d1$0$13933$fa0fcedb@news.zen.co.uk>
Ken Tilton wrote:
> Brian Adkins wrote:
>> On Sep 22, 11:18 pm, Ken Tilton <···········@optonline.net> wrote:
>>
>>> The Yobbos decided to punish me by forcing the survey off Cliki on the
>>> grounds that it was a commercial product.
>>
>>
>> What's commercial about the survey?
>>
> 
> Sorry, I collapsed a double-negative. The real reason was that some of 
> the people who responded do not produce non-commercial software... Hmmm, 
> that still sounds stupid.

No, the real reason was that Kenny asked to have it transferred.  See
http://groups.google.co.uk/group/comp.lang.lisp/msg/54c9edc3bfab90f2 and 
followups


-dan
From: Ken Tilton
Subject: Call for "Roads" [was some yobbo making things up]
Date: 
Message-ID: <GndMi.29$Qa3.3@newsfe12.lga>
···@telent.net wrote:
> Ken Tilton wrote:
> 
>> Brian Adkins wrote:
>>
>>> On Sep 22, 11:18 pm, Ken Tilton <···········@optonline.net> wrote:
>>>
>>>> The Yobbos decided to punish me by forcing the survey off Cliki on the
>>>> grounds that it was a commercial product.
>>>
>>>
>>>
>>> What's commercial about the survey?
>>>
>>
>> Sorry, I collapsed a double-negative. The real reason was that some of 
>> the people who responded do not produce non-commercial software... 
>> Hmmm, that still sounds stupid.
> 
> 
> No, the real reason was that Kenny asked to have it transferred. 

Chya. Your evidence begins with someone suggesting an adoptive home 
after you dropped the RtL off at Bradshaw's for melting down?  Why 
couldn't you have defended OJ?

If anyone wonders what we are talking about, what is left of the exiled 
affront to Clikidom can be found here in an ALU refugee camp:

   http://wiki.alu.org/RtL_Highlight_Film

Well, that's the highlight film. Click on each author to read the full 
story from which the highlight was extracted.

I have not hawked the thing in years, but the past six months have seen 
an awful lot of noobs, and it is still interesting how folks are finding 
Lisp. It will stop being interesting when O'Reilly starts soliciting 
Lisp titles.

kenny

ps. Maybe lemme know if you do one, here or by email. kt

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: ···@telent.net
Subject: Re: Call for "Roads" [was some yobbo making things up]
Date: 
Message-ID: <470169e8$0$13932$fa0fcedb@news.zen.co.uk>
Ken Tilton wrote:
> Chya. Your evidence begins with someone suggesting an adoptive home 
> after you dropped the RtL off at Bradshaw's for melting down?  Why 
> couldn't you have defended OJ?

Bradshaw's a yobbo now?  Either I missed something important while I was 
away, or the mind-control helicopters found something in my head to work 
on after all, cos I totally don't remember that.

> ps. Maybe lemme know if you do one, here or by email. kt

Do a RtL, or do an O'Reilly title?

http://wiki.alu.org/Daniel_Barlow's_Road_to_Lisp ; 2004-10-31
http://lemonodor.com/archives/000875.html        ; see third comment



-dan
From: Ken Tilton
Subject: Re: Call for "Roads" [was some yobbo making things up]
Date: 
Message-ID: <l1eMi.390$ET2.241@newsfe12.lga>
···@telent.net wrote:
> Ken Tilton wrote:
> 
>> Chya. Your evidence begins with someone suggesting an adoptive home 
>> after you dropped the RtL off at Bradshaw's for melting down?  Why 
>> couldn't you have defended OJ?
> 
> 
> Bradshaw's a yobbo now?  Either I missed something important while I was 
> away, or the mind-control helicopters found something in my head to work 
> on after all, cos I totally don't remember that.

All you have to do is ask around at Cliki HQ and find out who ordered 
the eviction of The Road to Lisp because (true) the Cliki charter is "of 
or pertaining to free Lisp software". Your non-countering 
counter-evidence picks up the story with the RtL sitting in a shelter 
waiting to be euthanized and someone suggesting an adoptive home.

> 
>> ps. Maybe lemme know if you do one, here or by email. kt
> 
> 
> Do a RtL, or do an O'Reilly title?

I was addressing the diaper-clad amongst us.

> 
> http://wiki.alu.org/Daniel_Barlow's_Road_to_Lisp ; 2004-10-31
> http://lemonodor.com/archives/000875.html        ; see third comment

I wonder if Peter saw an uptick this summer, I am doing my best to drive 
these rugrat pests out of here so they have to buy his book instead.

kt

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: Daniel Barlow
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <1188389161.2457.0@proxy02.news.clara.net>
Rob Warnock wrote:
>> For me, the two classic use cases [for specials] are:
> 
> 1. Things that work more-or-less like the ANSI-defined specials
>    such as *READ-BASE*, that is, large numbers of miscellaneous
>    global parameters that you *usually* want to just leave alone
>    but sometimes want to rebind for the dynamic extent of one
>    subtree of function calls.
> 
>    Thanks *goodness* for specials for this case!! Passing the ~20 (!)
>    or so specials that affect the Lisp printer [see CLHS 22.1.1.1]
>    around in every function call just to enforce some kind of
>    functional "purity" would simply be insane.

It's interesting you should use this as an example, because I've always 
thought the reader/printer variables would be much better suited as 
per-stream attributes of some kind

  (setf (stream-read-base myfile) 16)

than applying to every stream in some dynamic contour.  Otherwise you 
get really strange behaviour when you do

  (let ((*print-base* 13)) (some-computation))

and some-computation blows up landing you in the debugger.  Or if you 
don't get really strange behaviour it's only because the implementor has 
been to some lengths to have the debugger rebind everything again.


-dan
From: Matthias Buelow
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <5jal4jF3sr7rmU1@mid.dfncis.de>
Ken Tilton <···········@optonline.net> wrote:

> I meant to ask, when /should/ they be used?

There are some exceptional situations when they come in handy, don't
they. Like for providing a rarely used parameter that changes the
default behaviour of some mechanism deep in the bowels of some call tree
(where passing keywords down the whole thing isn't really practical and
positional parameters even less so). But not as an ordinary state
passing mechanism.

Yrs trly,
Slut.
From: Pascal Bourguignon
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <87ps1bwpm2.fsf@thalassa.informatimago.com>
Matthias Buelow <···@incubus.de> writes:

> Ken Tilton <···········@optonline.net> wrote:
>
>> I meant to ask, when /should/ they be used?
>
> There are some exceptional situations when they come in handy, don't
> they. Like for providing a rarely used parameter that changes the
> default behaviour of some mechanism deep in the bowels of some call tree
> (where passing keywords down the whole thing isn't really practical and
> positional parameters even less so). But not as an ordinary state
> passing mechanism.

There must be some globalness involved.


If you have only one "primitive" call that use it, like:

    (let ((*print-base* 8)) 
      (print 42))

it's hardly worth it, you could as well write:

    (write 42 :base 8)


It's worthwhile to use a CL special variable because it's a global
variable that will apply on ALL the functions that need it:

    (let ((*print-base* 8))
       (loop for i from 0 to 20 do
           (princ i) (princ ": ") (do-something-including-some-printing i)))



Using a special variable to store local state is not good style, when
you have in CL so many better alternatives. 

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
I need a new toy.
Tail of black dog keeps good time.
Pounce! Good dog! Good dog!
From: Ken Tilton
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <Tz7Ai.91$913.30@newsfe12.lga>
Matthias Buelow wrote:
> Ken Tilton <···········@optonline.net> wrote:
> 
> 
>>I meant to ask, when /should/ they be used?
> 
> 
> There are some exceptional situations when they come in handy, don't
> they. Like for providing a rarely used parameter that changes the
> default behaviour of some mechanism deep in the bowels of some call tree...

Oh, great, you figured out the reductio adsurbum case, and conceded that 
not all state seen by a function is a parameter to the functionality.

Now all you have to do is (a) learn how to program (b) do so for thirty 
years and then (c) try to come up with definition of where the line 
falls when deciding "special or parameter". Apparently you acknowledge 
already that overwrought scenery chewing with language like "ugly" and 
"impure" are fine for Usenet posturing, not so helpful for actually 
building software.

meanwhile, please explain how structured programming is a slippery slope 
inevitably leading to unmaintainable code. And relational design, and 
CLOS. And finite state machines. And why am I wasting time on a nincompoop?

kt

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: Matthias Buelow
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <5jeee2F3sp778U1@mid.dfncis.de>
Ken Tilton <···········@optonline.net> wrote:

> meanwhile, please explain how structured programming is a slippery slope 
> inevitably leading to unmaintainable code.

Anything eventually leads to unmaintainable code, the best you can do is
defer the inevitable horror a little bit. That's why software always
gets reinvented. Only dead programs never get replaced or rewritten.

> And why am I wasting time on a nincompoop?

No clue.. just keep on reading c.l.l... Keeps you away from the
nincompoops.
From: Dimiter "malkia" Stanev
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <5jk2afF3s02ktU1@mid.individual.net>
> Anything eventually leads to unmaintainable code, the best you can do is
> defer the inevitable horror a little bit. That's why software always
> gets reinvented. Only dead programs never get replaced or rewritten.

Yes software gets rewritten, but most of the time it just evolves (good 
or bad). The question is how easy are the tools to make the evolution 
easier. My daily job is C++, and everytime I add or change a virtual 
member function I have to recompile a bunch of .DLL's (or static .libs), 
or even if just add an optional argument, I have to do the same. Andnd 
sometimes I can't really evolove or change, bent the program behaviour, 
unless I rewrite whole portions of the code. At the same time, when I'm 
ready with the change, some other programmer might've already changed 
something and submitted to P4 before my stuff get's in. Most of the time 
I'm dealing with that.

I believe dynamic non-strict language like Common Lisp, Python, others 
would help evolving easier (even if that's not always creating correct 
code). I much rather prefer faster evolution, mutation, prototyping, 
called it what you want, than revolution, where you have to start either 
from scratch, or rewrite massive amounts of code to get your new feature.

I also like my P4 changelists to be really small as diffs.
From: Ken Tilton
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <qbjAi.24$AV2.8@newsfe12.lga>
Matthias Buelow wrote:
> Ken Tilton <···········@optonline.net> wrote:
> 
> 
>>I meant to ask, when /should/ they be used?
> 
> 
> There are some exceptional situations when they come in handy, don't
> they. Like for providing a rarely used parameter that changes the
> default behaviour of some mechanism deep in the bowels of some call tree
> (where passing keywords down the whole thing isn't really practical and
> positional parameters even less so). But not as an ordinary state
> passing mechanism.

Actually we are trying to decide if the OPs use case is ordinary or not, 
so the last sentence tells us nothing.

OK, now what happens if we listen to you and the state is passed as 
parameters along with other params. Now we have to do some 
refactoringtand state manipulation logic is moving one level deeper in 
to a subroutine, such that the original function no longer touches it? 
It just does some worjk and then calls one or another state-manipulating 
function to handle that task.  The original sadly still needs the state 
parameter purely to pass it along to the new state-manipulating subroutines.

Having a parameter just so you can pass it to someone else is one way 
God tells you to use a special.

kt

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: Ken Tilton
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <ORoAi.286$5R3.179@newsfe12.lga>
Matthias Buelow wrote:
> Ken Tilton <···········@optonline.net> wrote:
> 
> 
>>I meant to ask, when /should/ they be used?
> 
> 
> There are some exceptional situations when they come in handy, don't
> they.

No, there is nothing exceptional about it. The OP has a pile of state 
and a call tree. He knows, I know, and you know that the whole call tree 
is operating on the same pile of state. How can we best make that 
evident? Certainly not by creating non-parameterizing parameters to 
functions just to worship your God of Functional Purism. That in fact 
misleads readers to thinking that anyone anywhere can call the function 
with a different pile of state. Nonsense. That call tree is understood 
to work together on precisely one pile of state. No confusion arises, 
only clarity. Gosh, what is this thing I am working on? Oh *golly*, it's 
a special. Let's see the one fricking place it is bound. Holy crap, 
there are two. OK, in the middle of X we need to recursively invoke this 
subsystem on a different pile of state. Coolio.

You are a failed Lisper, and belong in the camp of Thou shalt have no 
god before me. You see specials, shreak in horror, and desperately 
demand they be confined, quarantined, constrained, and constricted to 
PRINT. Missing the whole point of Lisp. We have tools, lots of tools, 
lots of different kinds of tools, and lotsa paradigms. We do not what we 
fricking well please and write great code with it without a problem

You want there to be a problem, just like the strong static typers want 
there to be a problem. Unfortunately for all you finger shaking, rule 
making, strait jacket wearing school marms we have a nonexistence proof 
of craploads of great code being written without a problem in spite of 
your sky is falling obsessive compulsive gnashing of the teeth.

kt

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: Mark Cox
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <m1y7fxm3gl.fsf@gmail.com>
I happen to agree with Ken on this one, but I can understand the
concern the others have with not specifying all arguments.

Why couldn't you create a macro like:

(requires-specials (:vars ((*foo* (make-instance 'context)))
	 	    :parameters (*bar*)
		    :others (*a-special-already-defined-elsewhere*)
		    :append-doc-string "Requires special ~A")

  (defun myfunc (something) ...)
  (defun anotherfunc (something-else) ...)

  ;; I tend to assume that the specials are read only once you enter
  ;; the function tree, but I guess you could do something like this
  ;; aswell if you're really thorough.
  (modifies-special *bar*
    (defun something-that-modifies-*bar* (val) ...)))

Atleast this way you can tell from the indent that the functions are defined
inside something, and when you're not looking at the source,
the doc string for each function is modified. You could
also make requires-specials auto modify the doc string for each
special aswell by appending the functions that it has an effect on.

Mark
From: Sacha
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <2EQzi.70510$kj7.1999902@phobos.telenet-ops.be>
Matthias Buelow wrote:
> Ken Tilton <···········@optonline.net> wrote:
> 
>> The use case described by the OP is a good one for special variables. 
>> Those are not as unclean as classic globals.
> 
> Special variables are a poor and obscure alternative to functional
> arguments and shouldn't be used in place of them.
> 

I think that dynamic extent is conceptually very close to hidden 
functional arguments. With the added benefit that you can setf these in 
addition to regular let bindings.

These dynamic vars are not merely C constants. The dynamic extent is a 
pretty nice feature, let's use it !

Sacha
From: Alex Mizrahi
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <46d22161$0$90267$14726298@news.sunsite.dk>
(message (Hello 'Ken)
(you :wrote  :on '(Fri, 24 Aug 2007 15:25:45 -0400))
(

 ??>> You can pass the state as argument(s) (if practical) for a more
 ??>> functional approach... that's what I like doing although many here are
 ??>> really into setq/setf.

 KT> The use case described by the OP is a good one for special variables.

i agree with this -- most likely special variables will make most succinct, 
no-bullshit solution.
as Paul Graham wrote, succinctness is power :).

certainly there are some drawbacks like "namespace pollution" and "causing 
unpleasant interferences", but if that's not some part of large project, 
such drawbacks won't have any effect, and avoiding special variables in such 
cases are just kinda superstitions

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"choose no life") 
From: Pascal Bourguignon
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <87d4xdym4h.fsf@thalassa.informatimago.com>
"Erik R." <·············@gmail.com> writes:
> Greetings all.  I'm writing a simple min-max search program to
> practice my lisp.  I need 3 or 4 variables to represent the current
> state and then a few functions to change state and get possible future
> states.  My background is in java, so my first instinct was to make a
> CLOS object with slots and methods.  This quickly turned into a mess
> with every method starting with with-slots to make all the slot
> variables local and accessible.  I'm certain that this is a horribly
> disgusting approach in lisp and I was wondering what the proper way to
> go about this is.

Note, as disgusting as it may seem, it may still be quite efficient.
With a good implementation of CLOS, WITH-SLOTS can be as lightweight
as a LET, I think.

Anyways, the disgusting stuff you can hide it:

(defmacro define-method/slots (name arguments slots instance &body body)
  `(defmethod ,name ,arguments
     (with-slots ,slots ,instance
        ,@body)))

[Well you might want to process body more sophistically to put the
documentation string and the declarations in the right place].

(define-method/slots example ((self my-class) arg) 
     (my-first-slot my-other-slot) self
   (setf my-first-slot (* 2 my-other-slot)))



You could even make a more sophisticated macro to avoid repeatitively
giving the slots:

(with-slots/methods (my-first-slot my-other-slot) self

   (defmethod method-1 ((self my-class) arg...)
      (setf my-first-slot (* 2 my-other-slot)))

   (defmethod method-2 ((other other-class) (self my-class) arg...)
      (setf my-first-slot (* 3 my-other-slot)))

   ...)


with:


(defmacro with-slots/methods (slots instance &body body)
   ;; All form in BODY must be a DEFMETHOD
  `(progn
      ,@(mapcar (lambda (defmet)
                    (destructuring-bind (defmethod name arguments &rest body) defmet
                      (assert (eq 'defmethod defmethod))
                      `(defmethod ,name ,arguments
                          (with-slots ,slots ,instance ,@body))))
                body)))




> Do I surround my functions with a let that defines the variables?

That'd make a closure.  Closures and objects are "equivalent".

> A defstruct that I pass as a parameter to all my functions?

There's no WITH-FIELDS, but you can write one...  (You cannot use
with-slots on structures because the behavior of slot-value is not
specified for structures).



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

READ THIS BEFORE OPENING PACKAGE: According to certain suggested
versions of the Grand Unified Theory, the primary particles
constituting this product may decay to nothingness within the next
four hundred million years.
From: Scott Burson
Subject: Re: Maintaining multivariable state (newbie question)
Date: 
Message-ID: <1188023904.998350.208520@l22g2000prc.googlegroups.com>
On Aug 24, 6:36 am, "Erik R." <·············@gmail.com> wrote:

> A defstruct that I pass as a parameter to all my functions?

This would be my choice.  Standard objects (what you get when you use
DEFCLASS) have overhead for functionality you don't need; this is just
a tuple, it sounds like, not a full-blown class.  I try to avoid
specials most of the time, and anyway they don't sound like the right
thing for your situation, for reasons others have given.

Copying a small struct to change one slot (if you choose to do it that
way) is quite fast.

-- Scott