From: Wang Yin
Subject: How to create local state for functions?
Date: 
Message-ID: <m3oewan9ix.fsf@wangyin.com>
Hi, I'm new to Common Lisp, but I'm fairly familiar with Scheme. 
I want to master both now since all LISPs are so nice and useful!

Now I'm writing a function that creates nodes in a graph and number
each new node with a unique number.

In Scheme I could use define like this:

(define new-node
  (let ((serial 0))
    (lambda (x y)
      (set! serial (+ 1 serial))
      (list x y serial))))

(new-node 1 2)
;==> (1 2 1)
(new-node 3 4)
;==> (3 4 2)


In Common Lisp, must I write it like the following?

(setf (symbol-function 'new-node)
  (let ((serial 0))
    (lambda (x y)
      (setf serial (+ 1 serial))
      (list x y serial))))

Is there a nicer way to do this?


-- 
Yin Wang,
EDA Lab,
Deparment of Computer Science and Technology,
Tsinghua University,
100084
Beijing China

From: Howard Ding <······@hading.dnsalias.com>
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <m3ekx6zw5p.fsf@frisell.localdomain>
Wang Yin <··@wangyin.com> writes:

> (define new-node
>   (let ((serial 0))
>     (lambda (x y)
>       (set! serial (+ 1 serial))
>       (list x y serial))))
>
> (new-node 1 2)
> ;==> (1 2 1)
> (new-node 3 4)
> ;==> (3 4 2)
>
>
> In Common Lisp, must I write it like the following?
>
> (setf (symbol-function 'new-node)
>   (let ((serial 0))
>     (lambda (x y)
>       (setf serial (+ 1 serial))
>       (list x y serial))))
>
> Is there a nicer way to do this?
>

You could potentially do something like:

(let ((serial 0))
  (defun new-node (x y)
    (incf serial)
    (list x y serial)))

-- 
Howard Ding
<······@hading.dnsalias.com>
From: Luke Gorrie
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <lhismi4wjh.fsf@dodo.bluetail.com>
······@hading.dnsalias.com (Howard Ding <······@hading.dnsalias.com>) writes:

> You could potentially do something like:
> 
> (let ((serial 0))
>   (defun new-node (x y)
>     (incf serial)
>     (list x y serial)))

or

  (defvar *number-of-nodes* 0
    "Counter of the number of nodes created.")

  (defun new-node (x y)
    (list x y (incf *number-of-nodes*)))

I've always enjoyed the clarity of the closure approach in books, but
there's also something to be said for making the state more amenable
to inspection for debugging.

I once naively wrote production software with an ad-hoc home made
object system built from Scheme closures. It wasn't nearly as
comfortable as I'd hoped :-)

Another case was

  (define (my-accessor1 x) (cadr x))
vs.
  (define my-accessor2 cadr)

which look equivalent, but in practice the first one can help in
debugging:

  > my-accessor1
  #<procedure:my-accessor1>
  > my-accessor2
  #<primitive:cadr>

Just my 2c on some things they don't mention in textbooks :-)

Cheers,
Luke
From: Paul F. Dietz
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <eGGdndmU_I5vsgiiU-KYgA@dls.net>
Luke Gorrie wrote:

>   (defvar *number-of-nodes* 0
>     "Counter of the number of nodes created.")
> 
>   (defun new-node (x y)
>     (list x y (incf *number-of-nodes*)))
> 
> I've always enjoyed the clarity of the closure approach in books, but
> there's also something to be said for making the state more amenable
> to inspection for debugging.


The special variable approach also facilitates testing:

   (let ((*number-of-nodes* 0))
      <test-code>)

I find it useful not to use defvar, but to bind the special
variable around where I'm going to be using it.  This forces me to
think about the lifetime of the data, and also helps prevent
space leaks.  (handwave toward thread-safety too)

	Paul
From: Justin Dubs
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <2e262238.0310210612.2d60c24e@posting.google.com>
Wang Yin <··@wangyin.com> wrote in message news:<··············@wangyin.com>...
> Hi, I'm new to Common Lisp, but I'm fairly familiar with Scheme. 
> I want to master both now since all LISPs are so nice and useful!
> 
> Now I'm writing a function that creates nodes in a graph and number
> each new node with a unique number.
> 
> In Scheme I could use define like this:
> 
> (define new-node
>   (let ((serial 0))
>     (lambda (x y)
>       (set! serial (+ 1 serial))
>       (list x y serial))))
> 
> (new-node 1 2)
> ;==> (1 2 1)
> (new-node 3 4)
> ;==> (3 4 2)
> 
> 
> In Common Lisp, must I write it like the following?
> 
> (setf (symbol-function 'new-node)
>   (let ((serial 0))
>     (lambda (x y)
>       (setf serial (+ 1 serial))
>       (list x y serial))))
> 
> Is there a nicer way to do this?

Yes!  Just wrap your let-binding around the whole defun form...

(let ((serial -1))
  (defun new-node (x y)
    (list x y (incf serial))))

By the way, incf is Common Lisp's increment function.  The first
argument
is the place to be incremented and the optional second argument
specifies how much to increment it by.  The default is, of course, 1.

Hope this helps,

Justin Dubs
From: Steven M. Haflich
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <zYnlb.3026$2_7.1967@newssvr25.news.prodigy.com>
Justin Dubs wrote:

> By the way, incf is Common Lisp's increment function.

It's a macro, not a function.
From: Fogus
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <d1d8d7c9.0310210706.71b12902@posting.google.com>
Try this:

(let ((serial 0))
  (defun foo (x y)
    (setf serial (+ 1 serial))
    (list x y serial)))



-m


http://www.modus-ponens.com/blog/
From: Frank A. Adrian
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <7Kclb.1093$Yp5.9860@news.uswest.net>
Wang Yin wrote:

> (setf (symbol-function 'new-node)
>   (let ((serial 0))
>     (lambda (x y)
>       (setf serial (+ 1 serial))
>       (list x y serial))))

If you simply want a unique ID for the node, you could use gensym, too:

(defun make-node (x y) (list x y (gensym "node-")))

And, for that matter, if you are essentially building a struct, you might as
well just use:

(defstruct node (x y (serial (gensym "node-"))))

which will also define your accessors and your constructor function, as
well.

Remember to use that which is built in before rolling your own.  This is a
place where you probably don't need to set up a closure.

faa
From: Kaz Kylheku
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <cf333042.0310210948.65fbfa29@posting.google.com>
Wang Yin <··@wangyin.com> wrote in message news:<··············@wangyin.com>...
> Hi, I'm new to Common Lisp, but I'm fairly familiar with Scheme. 
> I want to master both now since all LISPs are so nice and useful!
> 
> Now I'm writing a function that creates nodes in a graph and number
> each new node with a unique number.
> 
> In Scheme I could use define like this:
> 
> (define new-node
>   (let ((serial 0))
>     (lambda (x y)
>       (set! serial (+ 1 serial))
>       (list x y serial))))

Here, you are depending on the behavior that the argument to define is
evaluated: it's just an expression which produces a value that is
bound to the variable new-node. The lambda expression produces a
function object and so the variable names a function.

In Lisp, DEFUN is a macro which creates the lambda closure internally
out of the body and parameter list, and the magic which sets up the
funtion binding of the specified symbol. The parameter and body
materials are *not* evaluated at all, but a closure is made at the
time when the DEFUN form as a whole is evaluated.

So the trick is to set up your lexical environment outside of the
DEFUN form:

  (let ((serial 0))
    (defun new-node (x y)
      (list x y (incf serial))))

When the LET is evaluated, the binding of SERIAL is established and
the DEFUN is evaluated. The closure then captures the binding of
SERIAL.

Another solution is to use the package system, with which you can
create your own private symbols for naming module variables.

  (defpackage :my-package
    :use :cl
    ... etc ...)

  (in-package :my-package)

  (defvar *serial-number* 0) ;; i.e. MY-PACKAGE::*SERIAL-NUMBER*

This is actually better because DEFVAR has some useful properties that
will become apparent when you dynamically re-load pieces of your
program while it is running.

Suppose that the software is running, and you want to replace the
NEW-NODE function. Well, guess what? Since you packaged the counter as
part of the captuerd lexical environment, you lose the serial counter
when you replace the function! The counter goes back to zero, and so
you start re-using numbers which may clash with existing nodes.

The DEFVAR construct ensures once-only initialization. If the variable
exists already, then additional DEFVAR forms do not store the initial
value, e.g.

  (defvar *x* 42)
  ;; *x* is 42

  (defvar *x* 43)
  ;; *x* is still 42!

So if you re-load a new version of the module that contains the
DEFVAR, it will not clobber the counter's value back to zero, in spite
of giving you newer versions of the functions.

So I would argue that module global variables are often better
represented by specials, in the light of the dynamic nature of Lisp,
and the package system gives you all the encapsulation you need to
prevent accidental misuse of those variables by foreign modules.

> In Common Lisp, must I write it like the following?
> 
> (setf (symbol-function 'new-node)
>   (let ((serial 0))
>     (lambda (x y)
>       (setf serial (+ 1 serial))
>       (list x y serial))))

This is probably not such a great idea because DEFUN does more than
just stuff a closure into the function binding. Take a look at the
macroexpansion of a DEFUN form on your Lisp system.

For one thing, there is no EVAL-WHEN, so the SETF form will always be
evaluated, whether the module is being compiled or loaded! You don't
need the NEW-NODE function to be defined inside the compiler's own
image.
From: Christophe Rhodes
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <sqd6cqjpsr.fsf@lambda.jcn.srcf.net>
···@ashi.footprints.net (Kaz Kylheku) writes:

> Wang Yin <··@wangyin.com> wrote in message news:<··············@wangyin.com>...
>> In Common Lisp, must I write it like the following?
>> 
>> (setf (symbol-function 'new-node)
>>   (let ((serial 0))
>>     (lambda (x y)
>>       (setf serial (+ 1 serial))
>>       (list x y serial))))
>
> This is probably not such a great idea because DEFUN does more than
> just stuff a closure into the function binding. Take a look at the
> macroexpansion of a DEFUN form on your Lisp system.
>
> For one thing, there is no EVAL-WHEN, so the SETF form will always be
> evaluated, whether the module is being compiled or loaded! You don't
> need the NEW-NODE function to be defined inside the compiler's own
> image.

The rest of Kaz' article was well-reasoned, but this is incorrect;
_because_ there is no eval-when, this form will not be evaluated when
compiled in a file; compilation will arrange for it to be evaluated at
load-time, as with other for-effect top-level forms.

The point about DEFUN doing more work, however, is well made; at the
very least, most environments will have an extra stanza to make the
fact that NEW-NODE will be fbound at load-time known to the compiler,
so that calls to NEW-NODE later on will not raise compile-time
style-warnings.

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Pascal Costanza
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <bn33sr$eu2$1@newsreader2.netcologne.de>
Wang Yin wrote:

> Hi, I'm new to Common Lisp, but I'm fairly familiar with Scheme. 
> I want to master both now since all LISPs are so nice and useful!
> 
> Now I'm writing a function that creates nodes in a graph and number
> each new node with a unique number.
> 
> In Scheme I could use define like this:
> 
> (define new-node
>   (let ((serial 0))
>     (lambda (x y)
>       (set! serial (+ 1 serial))
>       (list x y serial))))
> 
> (new-node 1 2)
> ;==> (1 2 1)
> (new-node 3 4)
> ;==> (3 4 2)
> 
> 
> In Common Lisp, must I write it like the following?
> 
> (setf (symbol-function 'new-node)
>   (let ((serial 0))
>     (lambda (x y)
>       (setf serial (+ 1 serial))
>       (list x y serial))))
> 
> Is there a nicer way to do this?

Yes:

(let ((serial 0))
   (defun new-node (x y)
     (incf serial)
     (list x y serial)))


Pascal
From: ·············@comcast.net
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <wuaywqmx.fsf@comcast.net>
Pascal Costanza <········@web.de> writes:

> Wang Yin wrote:
>
>> Hi, I'm new to Common Lisp, but I'm fairly familiar with Scheme. I
>> want to master both now since all LISPs are so nice and useful!
>> Now I'm writing a function that creates nodes in a graph and number
>> each new node with a unique number.
>>
>> In Scheme I could use define like this:
>> (define new-node
>>   (let ((serial 0))
>>     (lambda (x y)
>>       (set! serial (+ 1 serial))
>>       (list x y serial))))
>>
>> Is there a nicer way to do this?
>
> Yes:
>
> (let ((serial 0))
>    (defun new-node (x y)
>      (incf serial)
>      (list x y serial)))

Many people echoed this solution.  I wanted to point out to Wang Yin
that although DEFUN looks superficially like DEFINE, it definitely
does *not* act the same.  DEFUN is a macro that essentially expands into

(setf (symbol-function 'name) (lambda (bindings) body))

so

> (let ((serial 0))
>    (defun new-node (x y)
>      (incf serial)
>      (list x y serial)))

expands into

(let ((serial 0))
  (setf (symbol-function 'new-node)
        (lambda (x y)
          (incf serial)
          (list x y serial))))

thus having the effect you desire.

But you *cannot* use DEFUN to define `internal functions' ala Scheme.
Use FLET or LABELS for that purpose.
From: Matthieu Villeneuve
Subject: Re: How to create local state for functions?
Date: 
Message-ID: <3f95147d$0$27048$626a54ce@news.free.fr>
"Wang Yin" <··@wangyin.com> wrote in message
···················@wangyin.com...
>
> Hi, I'm new to Common Lisp, but I'm fairly familiar with Scheme.
> I want to master both now since all LISPs are so nice and useful!
>
> Now I'm writing a function that creates nodes in a graph and number
> each new node with a unique number.
>
> In Scheme I could use define like this:
>
> (define new-node
>   (let ((serial 0))
>     (lambda (x y)
>       (set! serial (+ 1 serial))
>       (list x y serial))))
>
> (new-node 1 2)
> ;==> (1 2 1)
> (new-node 3 4)
> ;==> (3 4 2)
>
>
> In Common Lisp, must I write it like the following?
>
> (setf (symbol-function 'new-node)
>   (let ((serial 0))
>     (lambda (x y)
>       (setf serial (+ 1 serial))
>       (list x y serial))))
>
> Is there a nicer way to do this?

(let ((serial 0))
  (defun new-node (x y)
    (incf serial)
    (list x y serial)))


--
Matthieu Villeneuve