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

Variable persistence: how?

2 views
Skip to first unread message

Mark Carter

unread,
Feb 20, 2004, 12:01:45 PM2/20/04
to
I read somewhere that it is possible to create variables in Scheme
which persist from call to call; but I can't seem to find the details.
I believe that they are called environments, and act like automatic
variables.

I have defined a function called fold-files-proc, which is called by
the standard Scheme fold-files function. I want to be able to write
something like:

(define (fold-files-proc start-pathname symbol accum)
(if (empty? accum)
(set root accum) ; <=== this isn't quite right
(cons (create-node root start-pathname symbol) accum)))

except that Scheme doesn't like the line
(set root accum)
The variable root is local to the function.

What should I be doing?

Jens Axel Søgaard

unread,
Feb 20, 2004, 2:06:55 PM2/20/04
to

Here is an example, where the variable
counter is made "persistent" for the
function counting-display.


(define counting-display 'uninitialized)

(let ([counter 0])
(set! counting-display
(lambda (x . more)
(if (null? more)
(begin
(set! counter (+ counter 1))
(display x))
(display counter))
(newline))))


>(counting-display 'a)
a
> (counting-display 'b)
b
> (counting-display 'show 'me)
2


--
Jens Axel Søgaard

Ray Dillinger

unread,
Feb 20, 2004, 2:08:47 PM2/20/04
to

Using lexical scope.

The usual method for creating functions with persistent local
variables is to define a higher-order function that builds them
for you (because you'll probably want more than one). Such
expressions use a lambda (typically syntactic-sugared as let)
to create a lexical region of code within which the arguments of
the lambda are visible. The function that uses those arguments as
persistent variables is then defined inside that lexical region
and has access to those variables.

Here is such a function in its 'canonical' form, which creates a
numeric accumulator.

(define make-accumulator
(lambda () ; this lambda defines the routine being bound to make-accumulator
(lambda (totl) ; this lambda is an 'anonymous' function called with arg of 0
(lambda (a) ; this lambda defines the routine being returned from make-accumulator.
(begin
(set! totl (+ totl a))
totl)))
0)) ; the zero here is the argument to the anonymous function.

=> make-accumulator

Here is the usual sugared syntax for it, rearranging the second
lambda into a let form and folding the first into an alternate
syntax of define.


(define (make-accumulator) ; <= first lambda sugared into this define.
(let ((totl 0)) ; <= second lambda sugared, becomes a let form.
(lambda (a) ; <= third lambda, the routine to be returned.
(begin
(set! totl (+ totl a))
totl)))) ; <= arg to second lambda has moved up into the let form.


either way, this creates a function which returns functions. And the
functions it returns each have access to their own little "static local
variable" named totl, and can set! it.

(define accum (make-accumulator)) =>accum
(define accum2 (make-accumulator)) =>accum2

(accum 2) => 2
(accum2 3) => 3
(accum 5) => 7
(accum2 -4) => -1
(accum 3) => 10
(accum2 5) => 4
(accum 0) => 10

In this example, I created two accumulators, accum and accum2. As
you can see, each has its own totl.

I hope you find this answer helpful. It's not directly addressing
the particular appliction you asked about, but understanding it
should give you the means to solve your problem.

Bear

Max Hailperin

unread,
Feb 20, 2004, 2:26:55 PM2/20/04
to
Jens Axel Søgaard <use...@jasoegaard.dk> writes:
...

> (define counting-display 'uninitialized)
>
> (let ([counter 0])
> (set! counting-display
> (lambda (x . more)
> (if (null? more)
> (begin
> (set! counter (+ counter 1))
> (display x))
> (display counter))
> (newline))))
...

For the inexperienced, it is worth pointing out that the above code
could be simplified to the version shown below. The version shown
above, with an initial definition as uninitialized and then a set! to
the real procedure, is only useful in that it illustrates a general
pattern that can be applied when several procedures need to share the
same state variables -- a situation that doesn't arise here.

(define counting-display
(let ((counter 0))


(lambda (x . more)
(if (null? more)
(begin
(set! counter (+ counter 1))
(display x))
(display counter))
(newline))))

-Max Hailperin
Associate Professor of Computer Science
Gustavus Adolphus College
800 W. College Ave.
St. Peter, MN 56082
USA
http://www.gustavus.edu/~max/

Mark Carter

unread,
Feb 21, 2004, 4:32:08 AM2/21/04
to
Ray Dillinger <be...@sonic.net> wrote in message news:<40365D4B...@sonic.net>...
> Mark Carter wrote:

> > What should I be doing?
>
> Using lexical scope.

> I hope you find this answer helpful. It's not directly addressing

> the particular appliction you asked about, but understanding it
> should give you the means to solve your problem.

That's great, thanks. I had in mind a general "how do you do it"
question regarding persistence, rather than just the specific issue
that I was tackling, anyway.

And thanks to the other respondants, too.

Jens Axel Søgaard

unread,
Feb 21, 2004, 7:58:33 AM2/21/04
to
Mark Carter wrote:

> That's great, thanks. I had in mind a general "how do you do it"
> question regarding persistence, rather than just the specific issue
> that I was tackling, anyway.

I'll recommend reading this section of SICP.

<http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#%_sec_3.1>

By the way, isn't the word "persistence" used to indicate that values
are kept from one program invocation to another (i.e. saved on disk or database) ?

A variable that keeps it's value from one function invocation to another is
in the C programming language called a static variable. Whether this coincides
with the terms normally used in semantics, I'm not quite sure.

--
Jens Axel Søgaard

Mark Carter

unread,
Feb 22, 2004, 4:40:18 AM2/22/04
to
Jens Axel Søgaard wrote:

> <http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#%_sec_3.1>

Thanks, I'll look into it. SICP is a book that I'd like to read, but
it's usually awkward for me to view it online. I can't seem to find a
download file for it in order to read it offline.

> By the way, isn't the word "persistence" used to indicate that values
> are kept from one program invocation to another (i.e. saved on disk or
> database) ?
>
> A variable that keeps it's value from one function invocation to another is
> in the C programming language called a static variable. Whether this
> coincides
> with the terms normally used in semantics, I'm not quite sure.

Apologies for the confusion - I meant static.

Thanks for code snippet, by the way. It will be a while before I
convince myself exactly how it works. Very mysterious - a local value
that still exists even though the function has returned.

Jens Axel Søgaard

unread,
Feb 22, 2004, 4:53:25 AM2/22/04
to
Mark Carter wrote:
> Jens Axel Søgaard [almost] wrote:

(define counting-display


(let ([counter 0])

(lambda (x . more)
(if (null? more)
(begin
(set! counter (+ counter 1))
(display x))
(display counter))
(newline))))

>> <http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#%_sec_3.1>

> Thanks for code snippet, by the way. It will be a while before I
> convince myself exactly how it works. Very mysterious - a local value
> that still exists even though the function has returned.

Note the variable COUNTER is bound *outside* the function.
The scope of the variable is body of the let-expression.
Seen from inside the lambda body there is no difference
between counter and a global variable. In fact, the
following version also works:

(define counter 0)
(define counting-display


(lambda (x . more)
(if (null? more)
(begin
(set! counter (+ counter 1))
(display x))
(display counter))
(newline)))

The only difference is that the scope of counter now is the entire top-level.

What you should focus on, is the scope of the variable (i.e. how the variable
is bound) and not on how it is used.

I hope, it's a little less mysterious now. Again, the explanation in SICP
is very good.

--
Jens Axel Søgaard

Jonadab the Unsightly One

unread,
Feb 24, 2004, 6:59:07 PM2/24/04
to
Jens Axel Søgaard <use...@jasoegaard.dk> writes:

> By the way, isn't the word "persistence" used to indicate that
> values are kept from one program invocation to another (i.e. saved
> on disk or database) ?

Depends which language camp you're in. C calls these things "static",
which of course they aren't. "persistent across calls" is more
precise, but it's also too verbose, so sometimes it gets shortened to
"persistent" despite the possible confusion with "persistent across
processes", "persistent across reboots", and so on. The concept goes
by other names as well.

--
$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}}
split//,"ten.thgirb\@badanoj$/ --";$\=$ ;-> ();print$/

Thant Tessman

unread,
Feb 25, 2004, 3:49:21 PM2/25/04
to
Jonadab the Unsightly One wrote:

> Jens Axel Søgaard <use...@jasoegaard.dk> writes:
>
>
>>By the way, isn't the word "persistence" used to indicate that
>>values are kept from one program invocation to another (i.e. saved
>>on disk or database) ?
>
>
> Depends which language camp you're in. C calls these things "static",
> which of course they aren't. "persistent across calls" is more
> precise, but it's also too verbose, so sometimes it gets shortened to
> "persistent" despite the possible confusion with "persistent across
> processes", "persistent across reboots", and so on. The concept goes
> by other names as well.

The keyword "static" in C is intended to refer to how the memory for the
variable is allocated. Compare "auto" and "extern".

I've only heard the term "persistence" used in the sense Jens Axel
Søgaard mentions.

-thant

Sander Vesik

unread,
Feb 25, 2004, 7:43:26 PM2/25/04
to
Jonadab the Unsightly One <jon...@bright.net> wrote:

> Jens Axel S?gaard <use...@jasoegaard.dk> writes:
>
> > By the way, isn't the word "persistence" used to indicate that
> > values are kept from one program invocation to another (i.e. saved
> > on disk or database) ?
>
> Depends which language camp you're in. C calls these things "static",
> which of course they aren't. "persistent across calls" is more

they have static addresses - unlike automatic variables (which gives you
the least used C variable qualifiers) that automaticly get a unused
address assigned to themselves.

> precise, but it's also too verbose, so sometimes it gets shortened to
> "persistent" despite the possible confusion with "persistent across
> processes", "persistent across reboots", and so on. The concept goes
> by other names as well.

most literature appears to use 'persistent' for things that do in
fact persist over all of these by being stored in a database.

>

--
Sander

+++ Out of cheese error +++

Geoffrey S. Knauth

unread,
Feb 29, 2004, 2:34:55 PM2/29/04
to
Mark Carter <carter...@ukmail.com> wrote:
> Jens Axel Søgaard wrote:
> > <http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#%_sec_3.1>
>
> Thanks, I'll look into it. SICP is a book that I'd like to read, but
> it's usually awkward for me to view it online. I can't seem to find a
> download file for it in order to read it offline.

Try: wget -r http://mitpress.mit.edu/sicp/full-text/book/book.html

--
Geoffrey S. Knauth | http://knauth.org/gsk

Mark Carter

unread,
Mar 1, 2004, 5:14:34 AM3/1/04
to
> > it's usually awkward for me to view it online. I can't seem to find a

> Try: wget -r http://mitpress.mit.edu/sicp/full-text/book/book.html

Thanks.

Although I actually used WinHTTrack Website Copier.

0 new messages