From: ·············@gmail.com
Subject: let and special variables: need more
Date: 
Message-ID: <5965baf9-4df5-4847-8f99-e0a2333eca88@x41g2000hsb.googlegroups.com>
Hello.

Here is the story of the day (following the implementation of the ring
buffer (yesterday's question), I was prompted to dig deeper into my
code, and realized that let and special variables do not behave as I
would have thought them to.  Baad variables.)

I wrote a utility (one dimensional differential equation solver) that
uses special variables for storing information (coefficients,
matrices, etc).  Here is a cartoon example.

(defpackage :dynamic-test
  (:use :cl)
  (:export :foo
	   :*a*
	   :*b*))

(in-package :dynamic-test)

(defvar *a* 5)
(defvar *b* 2)

(defun foo (arg)
  (+ (* *a* arg)
     *B*))

Now, I want to call foo, from other packages, but be able to overwrite
*a* and *b* depending on my need.  Here is an example

(defpackage :dynamic-test-user
  (:use :cl :dynamic-test))

(in-package :dynamic-test-user)

(let ((*a* 0)
      (*b* 1))
  (defun bar1 ()
    (foo 5)))

(defun bar2 ()
  (let ((*a* 0)
	(*b* 1))
    (foo 5)))

(let ((*a* 1)
      (*b* 3))
  (defun bar3 ()
    (foo 5)))

(defun bar4 ()
  (let ((*a* 1)
	(*b* 3))
    (foo 5)))

Cases bar1 and bar3 do not overwrite the values of *a* and *b*, but
cases bar2 and bar4 do.  The latter two correspond to the example in
PCL, Ch. 6.

But I would *really* like to make bar1 and bar3 work, because in
actuality, under each let, I would have several defuns under each let.

let ((*a* 0)
      (*b* 1))
  (defun bar1a ()
    (foo 5))
  (defun bar1b ()  ;;;  ** this is the important part
  (defun bar2b () ;;; ** same here
...)

I know that I could define an object, and go that route, but in my
naive enthusiasm, I was so sure that bar1 and bar3 would do what I
needed them to do.

Going back to my original problem.  What am I striving for?  I am
writing a 1D numerical simulation for a simple plasma problem.  The
problem solves several differential equations of the same form.  So, I
need to invoke the same solver (but with different coefficients)
several times (once for electrons, once for ions, once for potential,
once for ...

My plan was to have several let blocks, with each setting up the
environment for its problem by assigning values for the special
variables, and defining functions in each let block.   Then I would
have an exe-simulation function that would call the appropriate
solvers when needed.  I imagined that each solver would carry its own
special variables.

I thought this would work from my (evidently incorrect) reading of
closures and the let & lambda examples that I was reading.

So, is there some way of accomplishing this?  I guess the correct
question is: how to accomplish this?

Thank you for your time,

Mirko

PS -- this message and the example demonstrate my ignorance on the
topic.  What is actually happening in my code is that modifying the
specials in one let block, propagates to the specials in the other let
block.  I am still trying to reduce that to a simple example.

From: danb
Subject: Re: let and special variables: need more
Date: 
Message-ID: <22624698-38e4-4908-986d-bb2186ff3f3d@p25g2000hsf.googlegroups.com>
On Jun 24, 1:27 pm, ·············@gmail.com wrote:
> (defun foo (arg)
>   (+ (* *a* arg)
>      *B*))

> (let ((*a* 0)
>       (*b* 1))
>   (defun bar1 ()
>     (foo 5)))

> I need to invoke the same solver
> (but with different coefficients)
> how to accomplish this?

If you want to lock in the values of *a* and *b* at
compile time, then you need to lock in the definition
of foo.  The simplest way is to make it a macro:

(defmacro foo (arg)
  `(+ (* ,*a* ,arg)
     ,*b*))

If you need foo to be a function, then define
a new foo for each set of values:

(defmacro deffoo (foo)
  `(defun ,foo (arg)
    (+ (* ,*a* arg)
     ,*b*)))

--Dan

------------------------------------------------
http://www.prairienet.org/~dsb/

cl-match:  expressive pattern matching in Lisp
http://common-lisp.net/project/cl-match/
From: Kenny
Subject: Re: let and special variables: need more
Date: 
Message-ID: <48617cda$0$5009$607ed4bc@cv.net>
·············@gmail.com wrote:
> Hello.
> 
> Here is the story of the day (following the implementation of the ring
> buffer (yesterday's question), I was prompted to dig deeper into my
> code, and realized that let and special variables do not behave as I
> would have thought them to.  Baad variables.)
> 
> I wrote a utility (one dimensional differential equation solver) that
> uses special variables for storing information (coefficients,
> matrices, etc).  Here is a cartoon example.
> 
> (defpackage :dynamic-test
>   (:use :cl)
>   (:export :foo
> 	   :*a*
> 	   :*b*))
> 
> (in-package :dynamic-test)
> 
> (defvar *a* 5)
> (defvar *b* 2)
> 
> (defun foo (arg)
>   (+ (* *a* arg)
>      *B*))
> 
> Now, I want to call foo, from other packages, but be able to overwrite
> *a* and *b* depending on my need.  Here is an example
> 
> (defpackage :dynamic-test-user
>   (:use :cl :dynamic-test))
> 
> (in-package :dynamic-test-user)
> 
> (let ((*a* 0)
>       (*b* 1))
>   (defun bar1 ()
>     (foo 5)))
> 
> (defun bar2 ()
>   (let ((*a* 0)
> 	(*b* 1))
>     (foo 5)))
> 
> (let ((*a* 1)
>       (*b* 3))
>   (defun bar3 ()
>     (foo 5)))
> 
> (defun bar4 ()
>   (let ((*a* 1)
> 	(*b* 3))
>     (foo 5)))
> 
> Cases bar1 and bar3 do not overwrite the values of *a* and *b*, but
> cases bar2 and bar4 do.  The latter two correspond to the example in
> PCL, Ch. 6.
> 
> But I would *really* like to make bar1 and bar3 work, because in
> actuality, under each let, I would have several defuns under each let.
> 
> let ((*a* 0)
>       (*b* 1))
>   (defun bar1a ()
>     (foo 5))
>   (defun bar1b ()  ;;;  ** this is the important part
>   (defun bar2b () ;;; ** same here
> ...)
> 
> I know that I could define an object, and go that route, but in my
> naive enthusiasm, I was so sure that bar1 and bar3 would do what I
> needed them to do.
> 
> Going back to my original problem.  What am I striving for?  I am
> writing a 1D numerical simulation for a simple plasma problem.  The
> problem solves several differential equations of the same form.  So, I
> need to invoke the same solver (but with different coefficients)
> several times (once for electrons, once for ions, once for potential,
> once for ...
> 
> My plan was to have several let blocks, with each setting up the
> environment for its problem by assigning values for the special
> variables, and defining functions in each let block.   Then I would
> have an exe-simulation function that would call the appropriate
> solvers when needed.  I imagined that each solver would carry its own
> special variables.
> 
> I thought this would work from my (evidently incorrect) reading of
> closures and the let & lambda examples that I was reading.

I think your incorrect reading is of the word "dynamic". The behavior 
that bothers is exactly what you want and nothing else. You want the 
value of *a* (please fill in "and *b*" as we go) to be determined when 
it is accessed, not at compile time. That is what yoy got. Break out the 
champagne and be grateful you did not get what you wanted.

Everything worked. *a* got bound to 0, your Lisp thought, that's cute, I 
wonder why he did that, alls Im gonna do is compile bar1. It did and 
exited the scope in which you had dynamically bound *a*. Hell, the code 
compiled did not even mention *a*, but if it had, say with (print *a*), 
then the value printed would be the value bound to *a* /when the 
function actually runs/. Yeah!!!

> 
> So, is there some way of accomplishing this?  I guess the correct
> question is: how to accomplish this?

Good lord, why can you not just pass the variables? Are these things so 
deep and multitudinous the obvious must be eschewed?

Anyway, to do what you want you can just:

(let ((a 0))
    (defun bar1 ()
       (let ((*a* a))
          (foo 42)))
     ...repeat as many defuns as you like but each time include a 
dynamic binding /in each function's body/ as shown in bar1 to get, um, a 
dynamic binding. If that is a problem, cool, I met someone lazier than 
me, and you can write a really sick macro or macrolet to reduce the 
typing to a minimum. The macro would take apart each defun and 
reassemble it with the body wrapped in a new let as per hardcoded above.

(with-let-wrapping-each-fun-body ((*a* 0)(*b* 1))
     (defun bar1 ()
	(foo 5))
     (defun bar2 ...etc....))

Then post it here so we can all have a good laugh. Don't forget to use 
gensyms.

hth, kenny
From: Pascal Costanza
Subject: Re: let and special variables: need more
Date: 
Message-ID: <6cctmpF3c5f3aU1@mid.individual.net>
·············@gmail.com wrote:

> So, is there some way of accomplishing this?  I guess the correct
> question is: how to accomplish this?

Do you want something like this?

(defmacro sdefun (name (&rest parameters) &body body)
   `(defun ,name ,parameters
      (progv %variables %values
        ,@body)))

(defmacro slet ((&rest bindings) &body body)
   `(let ((%variables ',(mapcar #'first bindings))
          (%values (list ,@(mapcar #'second bindings))))
      ,@body))

(defvar *a* 0)
(defvar *b* 0)

(slet ((*a* (1+ *a*))
        (*b* (1+ *b*)))
   (sdefun foo ()
     (print *a*)
     (print *b*)))

 > (foo)
1
1


[Ahh, the virtues of unhygienic macros... ;) ]

Note: sdefun doesn't play nice with documentation strings and local 
declarations, but that's left as an exercise to the reader. ;)


Pascal

-- 
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: ·············@gmail.com
Subject: Re: let and special variables: need more
Date: 
Message-ID: <5ff7e507-0686-4b4b-b80f-fe8238f2a713@m36g2000hse.googlegroups.com>
On Jun 24, 2:45 pm, Pascal Costanza <····@p-cos.net> wrote:
> ·············@gmail.com wrote:
> > So, is there some way of accomplishing this?  I guess the correct
> > question is: how to accomplish this?
>
> Do you want something like this?
>
> (defmacro sdefun (name (&rest parameters) &body body)
>    `(defun ,name ,parameters
>       (progv %variables %values
>         ,@body)))
>
> (defmacro slet ((&rest bindings) &body body)
>    `(let ((%variables ',(mapcar #'first bindings))
>           (%values (list ,@(mapcar #'second bindings))))
>       ,@body))
>
> (defvar *a* 0)
> (defvar *b* 0)
>
> (slet ((*a* (1+ *a*))
>         (*b* (1+ *b*)))
>    (sdefun foo ()
>      (print *a*)
>      (print *b*)))
>
>  > (foo)
> 1
> 1
>
> [Ahh, the virtues of unhygienic macros... ;) ]
>
> Note: sdefun doesn't play nice with documentation strings and local
> declarations, but that's left as an exercise to the reader. ;)
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/

A couple of things.

First thank you very very much.

Second, I while I think I understand your dark magic, I don't think it
does exactly where I want it.  But with a few gensyms it might.

Here is a brief snippet of actual code, one of the let blocks.  The
starred variables are _all_ exported from the diff.eq. solver package
and are being modified for the poisson equation solver.

(let (*D-spatial* *F-spatial* *S_c-spatial* *S_p-spatial*)
  (defun load-poisson-coeffs ()
    (create-transp-vectors)
    (create-mat-vectors)
    (load-const-D 1d0)
    (load-const-F 0d0)
    (load-const-S_p 0d0))

  (defun calc-potential ()
    "Solve Poisson equation using the transport equation solver"
    (dotimes (iX *cX*)
      (setf (@iX *S_c-spatial*)
	    (0- ;; to adjust to sign convention of the transport equation
	     (/ (* (0- +e+) (- (@iX *ni-prof*)
			       (@iX *ne-prof*)))
		+eps0+))))
    (load-ss-mat *phi-l* *phi-r*)
    (print (aref pde-solvers::*f-spatial* 5))
    (setf *phi-prof* (solve-system))))

(@iX is an unhygienic macro that expands to (aref arg iX)).

The problem is that while my simulation is proceeding, a similar let
block with its own functions is also active for the electron density
and it is also modifying the special variables.  Since I am doing a
time evolution, I am calling functions from one block and then next
repeatedly, leading to cross-pollution.  I believed that cloaking them
in the let block would make them local to the functions defined in
their respective block.

I think I should expand your example and use gensym to create local
variables and then assign them to the specials when needed.  That
might be an overkill, and maybe I should switch to objects.

Mirko
From: Pascal Costanza
Subject: Re: let and special variables: need more
Date: 
Message-ID: <6cd4j6F3gm4etU1@mid.individual.net>
·············@gmail.com wrote:

> The problem is that while my simulation is proceeding, a similar let
> block with its own functions is also active for the electron density
> and it is also modifying the special variables.  Since I am doing a
> time evolution, I am calling functions from one block and then next
> repeatedly, leading to cross-pollution.  I believed that cloaking them
> in the let block would make them local to the functions defined in
> their respective block.

I don't quite understand what you are trying to achieve.

Are you saying that variables should only be rebound at top-level 
invocations of such functions, and that nested invocations should leave 
them untouched? That's how I interpret what you're saying.

Wouldn't it be easier to just bind the special variables at the call 
site (maybe by way of a special calling function)? You could export just 
these calling functions, but let the internal functions call each other 
directly.

Or is it something else that you want?


Pascal

-- 
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: Rainer Joswig
Subject: Re: let and special variables: need more
Date: 
Message-ID: <joswig-AEC2C5.23315324062008@news-europe.giganews.com>
In article 
<····································@x41g2000hsb.googlegroups.com>,
 ·············@gmail.com wrote:

> Hello.
> 
> Here is the story of the day (following the implementation of the ring
> buffer (yesterday's question), I was prompted to dig deeper into my
> code, and realized that let and special variables do not behave as I
> would have thought them to.  Baad variables.)
> 
> I wrote a utility (one dimensional differential equation solver) that
> uses special variables for storing information (coefficients,
> matrices, etc).  Here is a cartoon example.
> 
> (defpackage :dynamic-test
>   (:use :cl)
>   (:export :foo
> 	   :*a*
> 	   :*b*))
> 
> (in-package :dynamic-test)
> 
> (defvar *a* 5)
> (defvar *b* 2)
> 
> (defun foo (arg)
>   (+ (* *a* arg)
>      *B*))
> 
> Now, I want to call foo, from other packages, but be able to overwrite
> *a* and *b* depending on my need.  Here is an example
> 
> (defpackage :dynamic-test-user
>   (:use :cl :dynamic-test))
> 
> (in-package :dynamic-test-user)
> 
> (let ((*a* 0)
>       (*b* 1))
>   (defun bar1 ()
>     (foo 5)))

Not really sure about that, but I usually don't like
DEFUN being used in a LET.

One reason is that defining macros like defun may expand
into something that uses EVAL-WHEN :*-toplevel - like
 :compile-toplevel. But inside the LET, DEFUN is not
at the top-level, so those code will not get executed
at compile time.

Generally you need to understand that the dynamic binding
has effect when at the time the code executes.

You could use something like this using local functions.

(defun foo ()
   (let ((*bar* 'baz))
      (labels ((f1 ()
                 ...)
               (f2 (...)
                  ....))
          (f1 ...)
          (f2 ....))))


> 
> (defun bar2 ()
>   (let ((*a* 0)
> 	(*b* 1))
>     (foo 5)))
> 
> (let ((*a* 1)
>       (*b* 3))
>   (defun bar3 ()
>     (foo 5)))
> 
> (defun bar4 ()
>   (let ((*a* 1)
> 	(*b* 3))
>     (foo 5)))
> 
> Cases bar1 and bar3 do not overwrite the values of *a* and *b*, but
> cases bar2 and bar4 do.  The latter two correspond to the example in
> PCL, Ch. 6.
> 
> But I would *really* like to make bar1 and bar3 work, because in
> actuality, under each let, I would have several defuns under each let.
> 
> let ((*a* 0)
>       (*b* 1))
>   (defun bar1a ()
>     (foo 5))
>   (defun bar1b ()  ;;;  ** this is the important part
>   (defun bar2b () ;;; ** same here
> ...)
> 
> I know that I could define an object, and go that route, but in my
> naive enthusiasm, I was so sure that bar1 and bar3 would do what I
> needed them to do.
> 
> Going back to my original problem.  What am I striving for?  I am
> writing a 1D numerical simulation for a simple plasma problem.  The
> problem solves several differential equations of the same form.  So, I
> need to invoke the same solver (but with different coefficients)
> several times (once for electrons, once for ions, once for potential,
> once for ...
> 
> My plan was to have several let blocks, with each setting up the
> environment for its problem by assigning values for the special
> variables, and defining functions in each let block.   Then I would
> have an exe-simulation function that would call the appropriate
> solvers when needed.  I imagined that each solver would carry its own
> special variables.
> 
> I thought this would work from my (evidently incorrect) reading of
> closures and the let & lambda examples that I was reading.
> 
> So, is there some way of accomplishing this?  I guess the correct
> question is: how to accomplish this?
> 
> Thank you for your time,
> 
> Mirko
> 
> PS -- this message and the example demonstrate my ignorance on the
> topic.  What is actually happening in my code is that modifying the
> specials in one let block, propagates to the specials in the other let
> block.  I am still trying to reduce that to a simple example.

-- 
http://lispm.dyndns.org/
From: Vassil Nikolov
Subject: Re: let and special variables: need more
Date: 
Message-ID: <snzskv2ozv6.fsf@luna.vassil.nikolov.name>
On Tue, 24 Jun 2008 11:27:21 -0700 (PDT), ·············@gmail.com said:

| ...
| (defun foo (arg)
|   (+ (* *a* arg)
|      *B*))

  As a rule, free variables are not the programmer's friend.  (Or,
  free the programmers, not the variables.)  That said...

| ...
| (let ((*a* 0)
|       (*b* 1))
|   (defun bar1 ()
|     (foo 5)))

  To illustrate the difference, I can think of only one, rather
  unusual, case where one might bind special variables around a DEFUN
  form: if (a given Common Lisp implementation's) DEFUN can have some
  aspect of its behavior controlled by a special variable, like in
  this hypothetical example:

    * (defun foo (x) x)
    FOO
    * (let ((*defun-critic-p* t)) (defun foo (x) x))
    ;You may want to simply use CL:IDENTITY instead of FOO.
    FOO

  Otherwise, one would bind lexical variables around the DEFUN, as has
  been noted (which has its advantages and disadvantages, as has also
  been noted).  Perhaps the canonical textbook illustration is:

    (let ((balance 0))  ;state variable, mutated
      (defun change (amount) (incf balance amount))
      (defun inquire () balance))

    (inquire) => 0
    (change 100) => 100
    (inquire) => 100

  ---Vassil.


-- 
Peius melius est.  ---Ricardus Gabriel.
From: ·············@gmail.com
Subject: Re: let and special variables: need more
Date: 
Message-ID: <72a11600-d395-40e8-afae-17cc942b51ab@59g2000hsb.googlegroups.com>
On Jun 24, 2:27 pm, ·············@gmail.com wrote:
> Hello.
>
> Here is the story of the day (following the implementation of the ring
> buffer (yesterday's question), I was prompted to dig deeper into my
> code, and realized that let and special variables do not behave as I
> would have thought them to.  Baad variables.)
>
> I wrote a utility (one dimensional differential equation solver) that
> uses special variables for storing information (coefficients,
> matrices, etc).  Here is a cartoon example.
>
> (defpackage :dynamic-test
>   (:use :cl)
>   (:export :foo
>            :*a*
>            :*b*))
>
> (in-package :dynamic-test)
>
> (defvar *a* 5)
> (defvar *b* 2)
>
> (defun foo (arg)
>   (+ (* *a* arg)
>      *B*))
>
> Now, I want to call foo, from other packages, but be able to overwrite
> *a* and *b* depending on my need.  Here is an example
>
> (defpackage :dynamic-test-user
>   (:use :cl :dynamic-test))
>
> (in-package :dynamic-test-user)
>
> (let ((*a* 0)
>       (*b* 1))
>   (defun bar1 ()
>     (foo 5)))
>
> (defun bar2 ()
>   (let ((*a* 0)
>         (*b* 1))
>     (foo 5)))
>
> (let ((*a* 1)
>       (*b* 3))
>   (defun bar3 ()
>     (foo 5)))
>
> (defun bar4 ()
>   (let ((*a* 1)
>         (*b* 3))
>     (foo 5)))
>
> Cases bar1 and bar3 do not overwrite the values of *a* and *b*, but
> cases bar2 and bar4 do.  The latter two correspond to the example in
> PCL, Ch. 6.
>
> But I would *really* like to make bar1 and bar3 work, because in
> actuality, under each let, I would have several defuns under each let.
>
> let ((*a* 0)
>       (*b* 1))
>   (defun bar1a ()
>     (foo 5))
>   (defun bar1b ()  ;;;  ** this is the important part
>   (defun bar2b () ;;; ** same here
> ...)
>
> I know that I could define an object, and go that route, but in my
> naive enthusiasm, I was so sure that bar1 and bar3 would do what I
> needed them to do.
>
> Going back to my original problem.  What am I striving for?  I am
> writing a 1D numerical simulation for a simple plasma problem.  The
> problem solves several differential equations of the same form.  So, I
> need to invoke the same solver (but with different coefficients)
> several times (once for electrons, once for ions, once for potential,
> once for ...
>
> My plan was to have several let blocks, with each setting up the
> environment for its problem by assigning values for the special
> variables, and defining functions in each let block.   Then I would
> have an exe-simulation function that would call the appropriate
> solvers when needed.  I imagined that each solver would carry its own
> special variables.
>
> I thought this would work from my (evidently incorrect) reading of
> closures and the let & lambda examples that I was reading.
>
> So, is there some way of accomplishing this?  I guess the correct
> question is: how to accomplish this?
>
> Thank you for your time,
>
> Mirko
>
> PS -- this message and the example demonstrate my ignorance on the
> topic.  What is actually happening in my code is that modifying the
> specials in one let block, propagates to the specials in the other let
> block.  I am still trying to reduce that to a simple example.

Thanks to everyone.  I think I can summarize my aim and hope as
follows:

I was trying for a cheap "object" implementation.  The plan was to use
dynamic variables to save the state, and the functions to act upon
them.

Individual objects would have been initialize through the let blocks
where each let block would initialize its copy of the dynamic
variables, and the functions would act upon those local copies.

Baaad misreading of CL.  Back to the drawing board.

In some sense it is good news.  I thought I had a bad case of a
numeric instability.  Instead I only have a bad case of poor CL
understanding :-)

Thanks again.

Mirko
From: Pascal Costanza
Subject: Re: let and special variables: need more
Date: 
Message-ID: <6cf0qaF3gqb4eU1@mid.individual.net>
·············@gmail.com wrote:

> I was trying for a cheap "object" implementation.  The plan was to use
> dynamic variables to save the state, and the functions to act upon
> them.
> 
> Individual objects would have been initialize through the let blocks
> where each let block would initialize its copy of the dynamic
> variables, and the functions would act upon those local copies.

Cheap object implementations are typically done with lexical variables, 
not dynamic variables.

Something like this:

(let (name address employer)
   (lambda (msg &rest args)
     (case msg
       (get-name name)
       (set-name (setq name (first args)))
       ...
       (display (print name)
                (print address)
                (print employer))
       ...)))

This is very cheap and will probably break very soon (no inheritance, no 
interesting typing, only single dispatch, etc.).

I have read an abstract of a paper describing how to use dynamic scoping 
for a cheap object system, but didn't have enough time to read and 
understand it in detail. The above approach is the "classical" one.


Pascal

-- 
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: ·············@gmail.com
Subject: Re: let and special variables: need more
Date: 
Message-ID: <57bcbf28-b298-4493-ad0e-61ae38043582@25g2000hsx.googlegroups.com>
On Jun 25, 9:51 am, Pascal Costanza <····@p-cos.net> wrote:
> ·············@gmail.com wrote:
> > I was trying for a cheap "object" implementation.  The plan was to use
> > dynamic variables to save the state, and the functions to act upon
> > them.
>
> > Individual objects would have been initialize through the let blocks
> > where each let block would initialize its copy of the dynamic
> > variables, and the functions would act upon those local copies.
>
> Cheap object implementations are typically done with lexical variables,
> not dynamic variables.
>
> Something like this:
>
> (let (name address employer)
>    (lambda (msg &rest args)
>      (case msg
>        (get-name name)
>        (set-name (setq name (first args)))
>        ...
>        (display (print name)
>                 (print address)
>                 (print employer))
>        ...)))
>
> This is very cheap and will probably break very soon (no inheritance, no
> interesting typing, only single dispatch, etc.).
>
> I have read an abstract of a paper describing how to use dynamic scoping
> for a cheap object system, but didn't have enough time to read and
> understand it in detail. The above approach is the "classical" one.
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/

Yep.  I am looking at the examples in Graham's On Lisp section on
closures (specifically the example on Fig 2.1).

Mirko
From: Kenny
Subject: Re: let and special variables: need more
Date: 
Message-ID: <48626085$0$11631$607ed4bc@cv.net>
·············@gmail.com wrote:
> On Jun 25, 9:51 am, Pascal Costanza <····@p-cos.net> wrote:
>> ·············@gmail.com wrote:
>>> I was trying for a cheap "object" implementation.  The plan was to use
>>> dynamic variables to save the state, and the functions to act upon
>>> them.
>>> Individual objects would have been initialize through the let blocks
>>> where each let block would initialize its copy of the dynamic
>>> variables, and the functions would act upon those local copies.
>> Cheap object implementations are typically done with lexical variables,
>> not dynamic variables.
>>
>> Something like this:
>>
>> (let (name address employer)
>>    (lambda (msg &rest args)
>>      (case msg
>>        (get-name name)
>>        (set-name (setq name (first args)))
>>        ...
>>        (display (print name)
>>                 (print address)
>>                 (print employer))
>>        ...)))
>>
>> This is very cheap and will probably break very soon (no inheritance, no
>> interesting typing, only single dispatch, etc.).
>>
>> I have read an abstract of a paper describing how to use dynamic scoping
>> for a cheap object system, but didn't have enough time to read and
>> understand it in detail. The above approach is the "classical" one.
>>
>> Pascal
>>
>> --
>> My website:http://p-cos.net
>> Common Lisp Document Repository:http://cdr.eurolisp.org
>> Closer to MOP & ContextL:http://common-lisp.net/project/closer/
> 
> Yep.  I am looking at the examples in Graham's On Lisp section on
> closures (specifically the example on Fig 2.1).

(a) Have you observed a performance problem your cheap objects will solve?

(b) What makes you think your "cheap" objects will actually be cheaper 
than using defstruct?

I suspect the answers are "no" and "I just assume they will be".

ie, Stop it. Get back to work. (But do use structs, not CLOS.)

:)

kenny
From: ·············@gmail.com
Subject: Re: let and special variables: need more
Date: 
Message-ID: <ecd86e06-31a4-4e13-bc8a-5a7a3a96e53e@a1g2000hsb.googlegroups.com>
On Jun 25, 11:13 am, Kenny <·········@gmail.com> wrote:
> ·············@gmail.com wrote:
> > On Jun 25, 9:51 am, Pascal Costanza <····@p-cos.net> wrote:
> >> ·············@gmail.com wrote:
> >>> I was trying for a cheap "object" implementation.  The plan was to use
> >>> dynamic variables to save the state, and the functions to act upon
> >>> them.
> >>> Individual objects would have been initialize through the let blocks
> >>> where each let block would initialize its copy of the dynamic
> >>> variables, and the functions would act upon those local copies.
> >> Cheap object implementations are typically done with lexical variables,
> >> not dynamic variables.
>
> >> Something like this:
>
> >> (let (name address employer)
> >>    (lambda (msg &rest args)
> >>      (case msg
> >>        (get-name name)
> >>        (set-name (setq name (first args)))
> >>        ...
> >>        (display (print name)
> >>                 (print address)
> >>                 (print employer))
> >>        ...)))
>
> >> This is very cheap and will probably break very soon (no inheritance, no
> >> interesting typing, only single dispatch, etc.).
>
> >> I have read an abstract of a paper describing how to use dynamic scoping
> >> for a cheap object system, but didn't have enough time to read and
> >> understand it in detail. The above approach is the "classical" one.
>
> >> Pascal
>
> >> --
> >> My website:http://p-cos.net
> >> Common Lisp Document Repository:http://cdr.eurolisp.org
> >> Closer to MOP & ContextL:http://common-lisp.net/project/closer/
>
> > Yep.  I am looking at the examples in Graham's On Lisp section on
> > closures (specifically the example on Fig 2.1).
>
> (a) Have you observed a performance problem your cheap objects will solve?
>
> (b) What makes you think your "cheap" objects will actually be cheaper
> than using defstruct?
>
> I suspect the answers are "no" and "I just assume they will be".
>
> ie, Stop it. Get back to work. (But do use structs, not CLOS.)
>
> :)
>
> kenny

yep, that was the whole point.  I am trying not to use CLOS.  That was
one reason why I started looking into CL.  To get away from the oo
monstrosities that I was creating elsewhere.

:-)

Mirko
From: Kenny
Subject: Re: let and special variables: need more
Date: 
Message-ID: <4862786e$0$7355$607ed4bc@cv.net>
·············@gmail.com wrote:
> On Jun 25, 11:13 am, Kenny <·········@gmail.com> wrote:
>> ·············@gmail.com wrote:
>>> On Jun 25, 9:51 am, Pascal Costanza <····@p-cos.net> wrote:
>>>> ·············@gmail.com wrote:
>>>>> I was trying for a cheap "object" implementation.  The plan was to use
>>>>> dynamic variables to save the state, and the functions to act upon
>>>>> them.
>>>>> Individual objects would have been initialize through the let blocks
>>>>> where each let block would initialize its copy of the dynamic
>>>>> variables, and the functions would act upon those local copies.
>>>> Cheap object implementations are typically done with lexical variables,
>>>> not dynamic variables.
>>>> Something like this:
>>>> (let (name address employer)
>>>>    (lambda (msg &rest args)
>>>>      (case msg
>>>>        (get-name name)
>>>>        (set-name (setq name (first args)))
>>>>        ...
>>>>        (display (print name)
>>>>                 (print address)
>>>>                 (print employer))
>>>>        ...)))
>>>> This is very cheap and will probably break very soon (no inheritance, no
>>>> interesting typing, only single dispatch, etc.).
>>>> I have read an abstract of a paper describing how to use dynamic scoping
>>>> for a cheap object system, but didn't have enough time to read and
>>>> understand it in detail. The above approach is the "classical" one.
>>>> Pascal
>>>> --
>>>> My website:http://p-cos.net
>>>> Common Lisp Document Repository:http://cdr.eurolisp.org
>>>> Closer to MOP & ContextL:http://common-lisp.net/project/closer/
>>> Yep.  I am looking at the examples in Graham's On Lisp section on
>>> closures (specifically the example on Fig 2.1).
>> (a) Have you observed a performance problem your cheap objects will solve?
>>
>> (b) What makes you think your "cheap" objects will actually be cheaper
>> than using defstruct?
>>
>> I suspect the answers are "no" and "I just assume they will be".
>>
>> ie, Stop it. Get back to work. (But do use structs, not CLOS.)
>>
>> :)
>>
>> kenny
> 
> yep, that was the whole point.  I am trying not to use CLOS.  That was
> one reason why I started looking into CL.  To get away from the oo
> monstrosities that I was creating elsewhere.

Agreed, OO can get ugly, but be careful: CLOS is vastly better than 
other OO models, so do not assume you will create with it equally 
monstrous monstrosities. Second:

Baby. Bath water. Throw out exactly one.

Stendhal had a good line on infatuation lost, something about doing the 
objects of our desire two injustices, first setting them on too high a 
pedestal then rating them too low when they fall short of our first 
misappraisal. He said it better.

If you can see up front a performance issue (His Kennyness will allow 
you some guessing) you can start with structs. Or you can start with 
CLOS and go halfway -- do not do /everything/ via classes and GFs. Or go 
whole hog and see if it turns out better with CLOS than other models.

In the end any arbitrary rule can be a problem if it keeps us from 
thinking about the best way to do something. With a language like Lisp 
and a multitude of ways to do anything, it's better to Just Code and 
sort issues out in the context of the application, you'll go crazy if 
you are facing the CLHS instead of your problem.

Let us pray.

kt
From: ·············@gmail.com
Subject: Re: let and special variables: need more
Date: 
Message-ID: <9dab6ad8-a1c0-4a66-8f39-83fa6a295e4d@y38g2000hsy.googlegroups.com>
On Jun 25, 11:13 am, Kenny <·········@gmail.com> wrote:
> ·············@gmail.com wrote:
> > On Jun 25, 9:51 am, Pascal Costanza <····@p-cos.net> wrote:
> >> ·············@gmail.com wrote:
> >>> I was trying for a cheap "object" implementation.  The plan was to use
> >>> dynamic variables to save the state, and the functions to act upon
> >>> them.
> >>> Individual objects would have been initialize through the let blocks
> >>> where each let block would initialize its copy of the dynamic
> >>> variables, and the functions would act upon those local copies.
> >> Cheap object implementations are typically done with lexical variables,
> >> not dynamic variables.
>
> >> Something like this:
>
> >> (let (name address employer)
> >>    (lambda (msg &rest args)
> >>      (case msg
> >>        (get-name name)
> >>        (set-name (setq name (first args)))
> >>        ...
> >>        (display (print name)
> >>                 (print address)
> >>                 (print employer))
> >>        ...)))
>
> >> This is very cheap and will probably break very soon (no inheritance, no
> >> interesting typing, only single dispatch, etc.).
>
> >> I have read an abstract of a paper describing how to use dynamic scoping
> >> for a cheap object system, but didn't have enough time to read and
> >> understand it in detail. The above approach is the "classical" one.
>
> >> Pascal
>
> >> --
> >> My website:http://p-cos.net
> >> Common Lisp Document Repository:http://cdr.eurolisp.org
> >> Closer to MOP & ContextL:http://common-lisp.net/project/closer/
>
> > Yep.  I am looking at the examples in Graham's On Lisp section on
> > closures (specifically the example on Fig 2.1).
>
> (a) Have you observed a performance problem your cheap objects will solve?
>
> (b) What makes you think your "cheap" objects will actually be cheaper
> than using defstruct?
>
> I suspect the answers are "no" and "I just assume they will be".
>
> ie, Stop it. Get back to work. (But do use structs, not CLOS.)
>
> :)
>
> kenny

Foregive me, for I erred.  I went the CLOS route.  What a pain.  Next
time, I will try the structs.

mirko
From: Pascal Costanza
Subject: Re: let and special variables: need more
Date: 
Message-ID: <6ck7k2F3ftv6sU1@mid.individual.net>
·············@gmail.com wrote:
> On Jun 25, 11:13 am, Kenny <·········@gmail.com> wrote:
>> ·············@gmail.com wrote:
>>> On Jun 25, 9:51 am, Pascal Costanza <····@p-cos.net> wrote:
>>>> ·············@gmail.com wrote:
>>>>> I was trying for a cheap "object" implementation.  The plan was to use
>>>>> dynamic variables to save the state, and the functions to act upon
>>>>> them.
>>>>> Individual objects would have been initialize through the let blocks
>>>>> where each let block would initialize its copy of the dynamic
>>>>> variables, and the functions would act upon those local copies.
>>>> Cheap object implementations are typically done with lexical variables,
>>>> not dynamic variables.
>>>> Something like this:
>>>> (let (name address employer)
>>>>    (lambda (msg &rest args)
>>>>      (case msg
>>>>        (get-name name)
>>>>        (set-name (setq name (first args)))
>>>>        ...
>>>>        (display (print name)
>>>>                 (print address)
>>>>                 (print employer))
>>>>        ...)))
>>>> This is very cheap and will probably break very soon (no inheritance, no
>>>> interesting typing, only single dispatch, etc.).
>>>> I have read an abstract of a paper describing how to use dynamic scoping
>>>> for a cheap object system, but didn't have enough time to read and
>>>> understand it in detail. The above approach is the "classical" one.
>>>> Pascal
>>>> --
>>>> My website:http://p-cos.net
>>>> Common Lisp Document Repository:http://cdr.eurolisp.org
>>>> Closer to MOP & ContextL:http://common-lisp.net/project/closer/
>>> Yep.  I am looking at the examples in Graham's On Lisp section on
>>> closures (specifically the example on Fig 2.1).
>> (a) Have you observed a performance problem your cheap objects will solve?
>>
>> (b) What makes you think your "cheap" objects will actually be cheaper
>> than using defstruct?
>>
>> I suspect the answers are "no" and "I just assume they will be".
>>
>> ie, Stop it. Get back to work. (But do use structs, not CLOS.)
>>
>> :)
>>
>> kenny
> 
> Foregive me, for I erred.  I went the CLOS route.  What a pain.  Next
> time, I will try the structs.

That's good. The best way is always to try both options, and then decide 
for yourself.


Pascal

-- 
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: ·············@gmail.com
Subject: Re: let and special variables: need more
Date: 
Message-ID: <e1f8491c-beb7-4f41-8b2e-ad95f8449b2e@f36g2000hsa.googlegroups.com>
On Jun 27, 9:17 am, Pascal Costanza <····@p-cos.net> wrote:
> ·············@gmail.com wrote:
> > On Jun 25, 11:13 am, Kenny <·········@gmail.com> wrote:
> >> ·············@gmail.com wrote:
> >>> On Jun 25, 9:51 am, Pascal Costanza <····@p-cos.net> wrote:
> >>>> ·············@gmail.com wrote:
> >>>>> I was trying for a cheap "object" implementation.  The plan was to use
> >>>>> dynamic variables to save the state, and the functions to act upon
> >>>>> them.
> >>>>> Individual objects would have been initialize through the let blocks
> >>>>> where each let block would initialize its copy of the dynamic
> >>>>> variables, and the functions would act upon those local copies.
> >>>> Cheap object implementations are typically done with lexical variables,
> >>>> not dynamic variables.
> >>>> Something like this:
> >>>> (let (name address employer)
> >>>>    (lambda (msg &rest args)
> >>>>      (case msg
> >>>>        (get-name name)
> >>>>        (set-name (setq name (first args)))
> >>>>        ...
> >>>>        (display (print name)
> >>>>                 (print address)
> >>>>                 (print employer))
> >>>>        ...)))
> >>>> This is very cheap and will probably break very soon (no inheritance, no
> >>>> interesting typing, only single dispatch, etc.).
> >>>> I have read an abstract of a paper describing how to use dynamic scoping
> >>>> for a cheap object system, but didn't have enough time to read and
> >>>> understand it in detail. The above approach is the "classical" one.
> >>>> Pascal
> >>>> --
> >>>> My website:http://p-cos.net
> >>>> Common Lisp Document Repository:http://cdr.eurolisp.org
> >>>> Closer to MOP & ContextL:http://common-lisp.net/project/closer/
> >>> Yep.  I am looking at the examples in Graham's On Lisp section on
> >>> closures (specifically the example on Fig 2.1).
> >> (a) Have you observed a performance problem your cheap objects will solve?
>
> >> (b) What makes you think your "cheap" objects will actually be cheaper
> >> than using defstruct?
>
> >> I suspect the answers are "no" and "I just assume they will be".
>
> >> ie, Stop it. Get back to work. (But do use structs, not CLOS.)
>
> >> :)
>
> >> kenny
>
> > Foregive me, for I erred.  I went the CLOS route.  What a pain.  Next
> > time, I will try the structs.
>
> That's good. The best way is always to try both options, and then decide
> for yourself.
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/

Well, I gotta hand it to CLOS.  After the painful code conversion
(witness the large bold-french-roast Starbucks cups in the trash), it
worked just fine, and a two-level inheritance worked seamlessly.  I
was using lisp-unit to keep tabs that things were not being messed up.

Mirko
From: Pascal Costanza
Subject: Re: let and special variables: need more
Date: 
Message-ID: <6cf4phF3f77qlU1@mid.individual.net>
·············@gmail.com wrote:
> On Jun 25, 9:51 am, Pascal Costanza <····@p-cos.net> wrote:
>> Cheap object implementations are typically done with lexical variables,
>> not dynamic variables.
>>
>> Something like this:
>>
>> (let (name address employer)
>>    (lambda (msg &rest args)
>>      (case msg
>>        (get-name name)
>>        (set-name (setq name (first args)))
>>        ...
>>        (display (print name)
>>                 (print address)
>>                 (print employer))
>>        ...)))
>>
>> This is very cheap and will probably break very soon (no inheritance, no
>> interesting typing, only single dispatch, etc.).
>>
>> I have read an abstract of a paper describing how to use dynamic scoping
>> for a cheap object system, but didn't have enough time to read and
>> understand it in detail. The above approach is the "classical" one.
>>
>> Pascal
>>
>> --
>> My website:http://p-cos.net
>> Common Lisp Document Repository:http://cdr.eurolisp.org
>> Closer to MOP & ContextL:http://common-lisp.net/project/closer/
> 
> Yep.  I am looking at the examples in Graham's On Lisp section on
> closures (specifically the example on Fig 2.1).

Just for the sake of completeness: My strong recommendation is not to 
reinvent the wheel but just use CLOS. CLOS may seem complicated at first 
sight, but is actually quite easy to use, and provides most of what you 
need and then some.


Pascal

-- 
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: Vassil Nikolov
Subject: Re: let and special variables: need more
Date: 
Message-ID: <snz7icdotjz.fsf@luna.vassil.nikolov.name>
On Tue, 24 Jun 2008 11:27:21 -0700 (PDT), ·············@gmail.com said:
| ...
| (defun foo (arg)
|   (+ (* *a* arg)
|      *B*))
| ...
| (let ((*a* 0)
|       (*b* 1))
|   (defun bar1 ()
|     (foo 5)))

  It took me a while to ask, but it isn't currying that you are after,
  is it?  As in

    linear a b x = a*x + b
    id = linear 1 0

  so that

    id x => (linear 1 0) x => 1*x + 0 => x

  (borrowing an example from functional programming).

  *        *        *

  There is plenty of literature on how to do currying in Common Lisp;
  here is yet another example.

  A first approximation:

    *
    (defun curry (fn &rest cargs)
      #'(lambda (&rest args) (apply fn (append cargs args))))

    CURRY
    * (defun linear (a b x) (+ (* a x) b))

    LINEAR
    * (defun id (x) (funcall (curry #'linear 1 0) x))

    ID
    * (id 17)

    17

  The above (DEFUN ID ...) inefficiently conses up the curried
  function every time it is called, and is rather clunky, so we may
  want to introduce our own defining form instead:

    *
    ;; (defcurry id (linear 1 0))
    ;; -> (let ((cfn (curry #'linear 1 0)))
    ;;      (defun id (&rest args) (apply cfn args)))
    (defmacro defcurry (name (cfn &rest cargs))
      `(let ((cfn (curry #',cfn ,@cargs)))
         (defun ,name (&rest args) (apply cfn args))))

    DEFCURRY
    * (macroexpand-1 '(defcurry id (linear 1 0)))

    (LET ((CFN (CURRY #'LINEAR 1 0)))
      (DEFUN ID (&REST ARGS) (APPLY CFN ARGS)))
    T
    * (defcurry id (linear 1 0))
    STYLE-WARNING: redefining ID in DEFUN

    ID
    * (id 17)

    17

  Now, the above definition of CURRY is suboptimal in that it calls
  APPEND at every call; this is a small improvement:

    *
    (defun curry (fn &rest cargs)
      (destructuring-bind (&optional c0 c1 c2 &rest cetc) cargs
        (case (length cargs)
          (0 #'(lambda (&rest args) (apply fn args)))
          (1 #'(lambda (&rest args) (apply fn c0 args)))
          (2 #'(lambda (&rest args) (apply fn c0 c1 args)))
          (3 #'(lambda (&rest args) (apply fn c0 c1 c2 args)))
          (t #'(lambda (&rest args) (apply fn c0 c1 c2 (append cetc args)))))))
    STYLE-WARNING: redefining CURRY in DEFUN

    CURRY
    * (defcurry id (linear 1 0))
    STYLE-WARNING: redefining ID in DEFUN

    ID
    * (id 17)

    17

  ---Vassil.


-- 
Peius melius est.  ---Ricardus Gabriel.
From: Marco Antoniotti
Subject: Re: let and special variables: need more
Date: 
Message-ID: <04106740-3747-43bc-b687-067abead7480@f36g2000hsa.googlegroups.com>
On 26 Giu, 03:48, Vassil Nikolov <···············@pobox.com> wrote:
> On Tue, 24 Jun 2008 11:27:21 -0700 (PDT), ·············@gmail.com said:
> | ...
> | (defun foo (arg)
> |   (+ (* *a* arg)
> |      *B*))
> | ...
> | (let ((*a* 0)
> |       (*b* 1))
> |   (defun bar1 ()
> |     (foo 5)))
>
>   It took me a while to ask, but it isn't currying that you are after,
>   is it?  As in
>
>     linear a b x = a*x + b
>     id = linear 1 0
>
>   so that
>
>     id x => (linear 1 0) x => 1*x + 0 => x
>
>   (borrowing an example from functional programming).
>
>   *        *        *
>
>   There is plenty of literature on how to do currying in Common Lisp;
>   here is yet another example.
>
>   A first approximation:
>
>     *
>     (defun curry (fn &rest cargs)
>       #'(lambda (&rest args) (apply fn (append cargs args))))
>
>     CURRY
>     * (defun linear (a b x) (+ (* a x) b))
>
>     LINEAR
>     * (defun id (x) (funcall (curry #'linear 1 0) x))
>
>     ID
>     * (id 17)
>
>     17
>
>   The above (DEFUN ID ...) inefficiently conses up the curried
>   function every time it is called, and is rather clunky, so we may
>   want to introduce our own defining form instead:
>
>     *
>     ;; (defcurry id (linear 1 0))
>     ;; -> (let ((cfn (curry #'linear 1 0)))
>     ;;      (defun id (&rest args) (apply cfn args)))
>     (defmacro defcurry (name (cfn &rest cargs))
>       `(let ((cfn (curry #',cfn ,@cargs)))
>          (defun ,name (&rest args) (apply cfn args))))
>
>     DEFCURRY
>     * (macroexpand-1 '(defcurry id (linear 1 0)))
>
>     (LET ((CFN (CURRY #'LINEAR 1 0)))
>       (DEFUN ID (&REST ARGS) (APPLY CFN ARGS)))
>     T
>     * (defcurry id (linear 1 0))
>     STYLE-WARNING: redefining ID in DEFUN
>
>     ID
>     * (id 17)
>
>     17
>
>   Now, the above definition of CURRY is suboptimal in that it calls
>   APPEND at every call; this is a small improvement:
>
>     *
>     (defun curry (fn &rest cargs)
>       (destructuring-bind (&optional c0 c1 c2 &rest cetc) cargs
>         (case (length cargs)
>           (0 #'(lambda (&rest args) (apply fn args)))
>           (1 #'(lambda (&rest args) (apply fn c0 args)))
>           (2 #'(lambda (&rest args) (apply fn c0 c1 args)))
>           (3 #'(lambda (&rest args) (apply fn c0 c1 c2 args)))
>           (t #'(lambda (&rest args) (apply fn c0 c1 c2 (append cetc args)))))))
>     STYLE-WARNING: redefining CURRY in DEFUN
>
>

This screams for a DEFINE-COMPILER-MACRO.

Cheers
--
Marco
From: Vassil Nikolov
Subject: Re: let and special variables: need more
Date: 
Message-ID: <snz3an0pl2y.fsf@luna.vassil.nikolov.name>
On Thu, 26 Jun 2008 00:35:08 -0700 (PDT), Marco Antoniotti <·······@gmail.com> said:

| On 26 Giu, 03:48, Vassil Nikolov <···············@pobox.com> wrote:
|| ...
|| this is a small improvement:
|| 
|| *
|| (defun curry (fn &rest cargs)
|| (destructuring-bind (&optional c0 c1 c2 &rest cetc) cargs
|| (case (length cargs)
|| (0 #'(lambda (&rest args) (apply fn args)))
|| (1 #'(lambda (&rest args) (apply fn c0 args)))
|| (2 #'(lambda (&rest args) (apply fn c0 c1 args)))
|| (3 #'(lambda (&rest args) (apply fn c0 c1 c2 args)))
|| (t #'(lambda (&rest args) (apply fn c0 c1 c2 (append cetc args)))))))
|| STYLE-WARNING: redefining CURRY in DEFUN

| This screams for a DEFINE-COMPILER-MACRO.

  Quite so, but the dog ate it last night (a call which lasted for a
  couple of hours...).

  ---Vassil.


-- 
Peius melius est.  ---Ricardus Gabriel.
From: ·············@gmail.com
Subject: Re: let and special variables: need more
Date: 
Message-ID: <2b22f490-5fad-4b7f-b944-4e46c679e674@y21g2000hsf.googlegroups.com>
On Jun 25, 9:48 pm, Vassil Nikolov <···············@pobox.com> wrote:
> On Tue, 24 Jun 2008 11:27:21 -0700 (PDT), ·············@gmail.com said:
> | ...
> | (defun foo (arg)
> |   (+ (* *a* arg)
> |      *B*))
> | ...
> | (let ((*a* 0)
> |       (*b* 1))
> |   (defun bar1 ()
> |     (foo 5)))
>
>   It took me a while to ask, but it isn't currying that you are after,
>   is it?  As in
>
>     linear a b x = a*x + b
>     id = linear 1 0
>
>   so that
>
>     id x => (linear 1 0) x => 1*x + 0 => x
>
>   (borrowing an example from functional programming).
>
>   *        *        *
>
>   There is plenty of literature on how to do currying in Common Lisp;
>   here is yet another example.
>
>   A first approximation:
>
>     *
>     (defun curry (fn &rest cargs)
>       #'(lambda (&rest args) (apply fn (append cargs args))))
>
>     CURRY
>     * (defun linear (a b x) (+ (* a x) b))
>
>     LINEAR
>     * (defun id (x) (funcall (curry #'linear 1 0) x))
>
>     ID
>     * (id 17)
>
>     17
>
>   The above (DEFUN ID ...) inefficiently conses up the curried
>   function every time it is called, and is rather clunky, so we may
>   want to introduce our own defining form instead:
>
>     *
>     ;; (defcurry id (linear 1 0))
>     ;; -> (let ((cfn (curry #'linear 1 0)))
>     ;;      (defun id (&rest args) (apply cfn args)))
>     (defmacro defcurry (name (cfn &rest cargs))
>       `(let ((cfn (curry #',cfn ,@cargs)))
>          (defun ,name (&rest args) (apply cfn args))))
>
>     DEFCURRY
>     * (macroexpand-1 '(defcurry id (linear 1 0)))
>
>     (LET ((CFN (CURRY #'LINEAR 1 0)))
>       (DEFUN ID (&REST ARGS) (APPLY CFN ARGS)))
>     T
>     * (defcurry id (linear 1 0))
>     STYLE-WARNING: redefining ID in DEFUN
>
>     ID
>     * (id 17)
>
>     17
>
>   Now, the above definition of CURRY is suboptimal in that it calls
>   APPEND at every call; this is a small improvement:
>
>     *
>     (defun curry (fn &rest cargs)
>       (destructuring-bind (&optional c0 c1 c2 &rest cetc) cargs
>         (case (length cargs)
>           (0 #'(lambda (&rest args) (apply fn args)))
>           (1 #'(lambda (&rest args) (apply fn c0 args)))
>           (2 #'(lambda (&rest args) (apply fn c0 c1 args)))
>           (3 #'(lambda (&rest args) (apply fn c0 c1 c2 args)))
>           (t #'(lambda (&rest args) (apply fn c0 c1 c2 (append cetc args)))))))
>     STYLE-WARNING: redefining CURRY in DEFUN
>
>     CURRY
>     * (defcurry id (linear 1 0))
>     STYLE-WARNING: redefining ID in DEFUN
>
>     ID
>     * (id 17)
>
>     17
>
>   ---Vassil.
>
> --
> Peius melius est.  ---Ricardus Gabriel.

No, what I had in mind is illustrated with the following code
(stealing shamelessly from Graham, and possibly Hoyte) (but see below
how I first tried).

(defun create-util ()
  (let ((a 1)
	(b 2))
    (list
       (cons 'seta #'(lambda (arg)
	 (setf a arg)))
       (cons 'sum #'(lambda ()
	 (+ a b)));;)
       (cons 'vals #'(lambda ()
       (format t "A, B= ~D, ~D~%" a b))))))

(defun exe (util method &rest args)
  (apply (cdr (assoc method util)) args))

Now I can do
ETEST-USER> (defvar *u1* (create-util))
*U1*
ETEST-USER> (defvar *u2* (create-util))
*U2*
ETEST-USER> (exe *u2* 'seta -3)
-3
ETEST-USER> (exe *u1* 'vals)
A, B= 1, 2
NIL
ETEST-USER> (exe *u2* 'vals)
A, B= -3, 2
NIL

I mean, this is all elementary closures stuff.

What I was shooting for was an misunderstood attempt to usurp global
variables.  The following snippet illustrates my incorrect attempt.
;;; Define "dummy" dynamic vars and define functions that operate on
them
(defvar *a* 1)
(defvar *b* 2)

(defun seta* (arg) (setf *a* arg))
(defun sum* () (+ *a* *b*))
(defun vals* ()
  (format t "A, B= ~D, ~D~%" *a* *b*))

;;; Define block 1 that has functions to modify the dynamic vars and
operate on them
(let ((*a* 5)
      (*b* 6))
  (defun seta-1 (arg)
    (setf *a* arg))
  (defun vals-1 ()
    (vals)))

;;; Define block 2 that assigns different values to dynamic vars.
(let ((*a* -5)
      (*b* -6))
  (defun vals-2 ()
    (vals)))

My hope was that the functions sum* vals* seta* would exist separately
in blocks 1 & 2 with their OWN COPIES of *a* and *b*.  That is how I
misunderstood the simple examples in Practical Common Lisp.

As discussed before, I was hoping to avoid the use of objects, mostly
for philosophical reasons (why use them if not absolutely necessary),
and I thought that my need was simple enough.

So, as the first code (with let & closures) shows, I can do it, but I
think that as I keep adding stuff to my utility, (right now I am
mainly thinking of optional, rest & keyword arguments) I will start
reinventing the wheel.

Mirko
From: Vassil Nikolov
Subject: Re: let and special variables: need more
Date: 
Message-ID: <snzvdzvo7ij.fsf@luna.vassil.nikolov.name>
On Thu, 26 Jun 2008 07:44:10 -0700 (PDT), ·············@gmail.com said:

| No, what I had in mind is illustrated with the following code
| (stealing shamelessly from Graham, and possibly Hoyte) (but see below
| how I first tried).

  I see, so I misunderstood earlier.

| (defun create-util ()
|   (let ((a 1)
|         (b 2))
|     ...))

  As a side note, a function like the above often needs to change so
  that A and B are formal parameters.  Sometimes one "oscillates"
  between the two variants (e.g. in exploratory programming mode), and
  it is in such cases that &AUX, sometimes disparaged, may be handy:
  it is much easier to switch between

    (defun create-util (&aux (a 1) (b 2)) ...)

  and

    (defun create-util (&optional (a 1) (b 2)) ...)

  than between the latter and a nested LET.  The third
  easy-to-switch-to variant is, of course,

    (defun create-util (&key (a 1) (b 2)) ...)

  when one hasn't yet made up one's mind whether to supply arguments
  by position or by keyword.

| ...
| What I was shooting for was an misunderstood attempt to usurp global
| variables.  The following snippet illustrates my incorrect attempt.
| ;;; Define "dummy" dynamic vars and define functions that operate on
| them
| (defvar *a* 1)
| (defvar *b* 2)

| (defun seta* (arg) (setf *a* arg))
| (defun sum* () (+ *a* *b*))
| (defun vals* ()
|   (format t "A, B= ~D, ~D~%" *a* *b*))

| ;;; Define block 1 that has functions to modify the dynamic vars and
| operate on them
| (let ((*a* 5)
|       (*b* 6))
|   (defun seta-1 (arg)
|     (setf *a* arg))
|   (defun vals-1 ()
|     (vals)))

| ;;; Define block 2 that assigns different values to dynamic vars.
| (let ((*a* -5)
|       (*b* -6))
|   (defun vals-2 ()
|     (vals)))

| My hope was that the functions sum* vals* seta* would exist separately
| in blocks 1 & 2 with their OWN COPIES of *a* and *b*.  That is how I
| misunderstood the simple examples in Practical Common Lisp.

  Now, as a rule dynamic variables are not the way to go here, as has
  already been said, but as an _exercise_, something like the above
  can be done using PROGV.  The idea would be to represent each
  function in the above "blocks" by a pair of (1) a list of (variable,
  value) pairs and (2) the code (one of #'SETA*, #'SUM*, etc.)  Then a
  call to, say, SETA-1 would execute PROGV, (re)establishing the
  bindings from the first element of the corresponding pair, and
  within that PROGV (a) call SETA* (i.e. the second element of the
  same pair), (b) update the list of bindings with any changed values,
  and (c) return the value that the call to SETA* returned.

  Some treatment of this broad area from Lisp's pre-lexical-scope days
  is in Joel Moses's paper "The Function of FUNCTION in Lisp".

  ---Vassil.


-- 
Peius melius est.  ---Ricardus Gabriel.