Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

Scheme Programming Language

newbie - remembering state (using let) using paramterless procedure


Hi all,

The problem: design a procedure called USHER that takes no
params.  Each time it is called, it checks to see if there
are any seats left.  If there are, the procedure returns a
ticket number otherwise "Sorry. No seats left."  The number
of seats must be contained inside this procedure - not
accessible to other procedures.

Expected results:
(usher) ; returns 1
(usher) ; returns 2
(usher) ; returns 3
(usher) ; returns "Sorry, sold out!"
(usher) ; returns "Sorry, sold out!"

I am clueless about HOW to approach this problem.  I can't
get past this issue: logically, I would expect that each
time a parameterless procedure was called then all local
variables inside its environment would be reinitialised.  I
am told it can be done - but have seen no code examples that
show the technique.

For me, this has been a really interesting issue of scoping
variables - and at a guess, I'd say my problem lies in where
I placed the variable needing to change.  Of course, I am
most likely completely wrong :)

Could someone kindly nudge me in the right direction?

My code is below.

Kindest regards,

Mike
;--------------
;This is what I have done (does not work):

(define (usher)
  (let ((max-seats 3)
        (last-ticket 0))
    (if (equal? last-ticket max-seats)
        "Sorry Sold Out."
        (begin
          (set! last-ticket (+ last-ticket 1))
          last-ticket))))
; Each time the procedure is called the value for
; last-ticket is reinitialised to 0 and the result always 1.

; This is a snap if the number of available seats was
external.

(define seats 3)
(define next-ticket 0)
(define (usher)
  (if (equal? seats next-ticket)
      "Sorry, sold out!"
      (begin
        (set! next-ticket (+ next-ticket 1))
        next-ticket
        )))

; I tried an different approach
; (building a string on each call) and it too fails.
;
(define (build-string)
  (let [[string-so-far ""]]
    (define accumulate-strings
      (let [[temp-string string-so-far]]
        (define [add-string new-string]
          (begin
            (set! temp-string
                  (string-append temp-string
                                 new-string))
            temp-string))
        add-string))
    (begin
      (set! string-so-far
            (string-append
             string-so-far
             (accumulate-strings "a")))
      string-so-far)))
(build-string) ; returns "a"
(build-string) ; returns "a"
(build-string) ; returns "a"

Yes, just do it as you say!  It's indeed a question of scope.

So you know that when you put the variable inside the function it gets
reinitialized everytime you enter the function. Therefore you need to
put the variable outside of the function, as in:

> ; This is a snap if the number of available seats was
> external.

> (define seats 3)
> (define next-ticket 0)
> (define (usher)
>   (if (equal? seats next-ticket)
>       "Sorry, sold out!"
>       (begin
>         (set! next-ticket (+ next-ticket 1))
>         next-ticket
>         )))

Or, if you want a local variable, use let, but put the function inside:

C/SCHEME[141]> (define usher (let ((seats 3)
                                   (next-ticket 0))
                               (lambda ()
                                 (if (= seats next-ticket)
                                     "Sorry, sold out!"
                                     (begin
                                      (set! next-ticket (+ 1 next-ticket))
                                      next-ticket)))))
usher defined.
C/SCHEME[142]> (usher)
1
C/SCHEME[143]> (usher)
2
C/SCHEME[144]> (usher)
3
C/SCHEME[145]> (usher)
"Sorry, sold out!"
C/SCHEME[146]>

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

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.

Construct a function which, when evaluated, returns the
function you want. Call that function with an argument
giving the number of seats.

Then, because the function you want is local to the function
that defined it, in lexical scope, it can see the argument
of the function that created it.

Here's a way.

(define usher
    (lambda (numseats)
       (lambda ()
           (if (<= numseats 0)
               "sorry, sold out!"
               (begin
                  (set! numseats (- numseats 1))
                  numseats))) 3)

Now, the way you read this is:

(define usher
    (anonymous-function 3))

Usher is the result of calling the anonymous function
with an argument of 3.

Not coincidentally, there's a form "let" defined for
convenience that does this same trick.  In order to
use it, you'd write:

(define usher
    (let ((numseats 3))  ;; let defines the anonymous
                         ;; function from above and calls
                         ;; it with argument 3
       ... code for usher ...
    ) )

But I prefer using "lambda" to explain it because it's
clearer what "lambda" does.

                                Bear

Hi Pascall,

Your solution makes perfect sense ... This is really amazing
to me :)  Silly, no?  Until I saw this I would not have
believed it possible but it really makes perfect sense.
Light bulbs going off - that lambda expression could do a
lot of different things if I wanted.  For example, by adding
a flag msg to the local variable list, I could tell how many
times the procedure had been called and then branch..

(define usher
  (let ((seats 3)
        (next-ticket 0)
        (msg 0))
    (lambda ()
      (cond
        [(equal? msg 2) 'Go-away!]
        [else
         (if (= seats next-ticket)
             "Sorry, sold out!"
             (begin
               (set! next-ticket (+ 1 next-ticket))
               (set! msg (+ msg 1))
               next-ticket))]))))

Embarrassingly, I was closest on my first attempt.  I could
not manage to get the code to work when I named the lambda
expression (force of habit).  My broken code is below.  This
returned 1 each time usher was called.  (same as the code I
first presented).

It's not what I wanted but what I expected - frustrating.
Stepper is great for seeing what is happening inside the
code.  In your solution the let statement is processed
once - at the time usher is defined.  Each time usher is
applied, the lambda expression is evaluated - the let
statement is not touched again.

Aside from habit, another reason I used the approach (below)
was to see if I might add a degree of flexibility with a
pram tickets-required in the named procedure (might want to
give more than one ticket).  BTW - the code didn't check if
tickets-required resulted in a negative ... could not get it
to work with a param value of 1 :)

Can you correct my thoughts on your approach?  Your code
does not enclose usher in brackets - it doesn't need to
because it contains a lambda expression which is the
procedure applied when usher is called.  This explains WHY
usher needed to be enclosed in brackets.  However if I do
this: (define foo (* 1 2 3 4))  then foo is a constant
(assuming I do not redefine it - bad technique). I cannot
enclose foo in brackets any more than I could (10) -
generates an error.  In both instances, the existence of
brackets denotes that a procedure is to be applied - and
instead of a procedure I gave foo (containing the value 24)
and the numeric constant 10.  Is this correct?

The purpose of the exercise was to isolate the environment
inside usher from being accessed externally, while still
allowing usher to 'remember' it's internal state (previous
value).  My code (below) always caused the local variables
to be initialised - and I can see why.  Is there any way to
name the lambda expression - and potentially add params
(tickets-required might be the value of another procedure
for example)?  Just curious.  I was aware of using (unnamed)
lambda expressions - and until now, considered this to be
convenience as opposed to requirement.

Or is my thinking well off - as in, the lambda expression in
your code is named and is called usher?

Kindest regards,

Mike
---------
(define (usher)
  (let ((seats 3)
        (next-ticket 0))
      (define (give-ticket tickets-required)
        (if (= seats next-ticket)
            "Sorry! Sold out."
            (begin
              (set! next-ticket (+ next-ticket
tickets-required))
              next-ticket)))
      (give-ticket 1)))

"Pascal Bourguignon" <p@informatimago.com> wrote in
message
news:87myzjaxws.fsf@thalassa.lan.informatimago.com...

| "Mike" <mcu87@bigpond.net.au> writes:

|
| > Hi all,
| >
| > The problem: design a procedure called USHER that takes
no
| > params.  Each time it is called, it checks to see if
there
| > are any seats left.  If there are, the procedure returns
a
| > ticket number otherwise "Sorry. No seats left."  The
number
| > of seats must be contained inside this procedure - not
| > accessible to other procedures.
| >
| > Expected results:
| > (usher) ; returns 1
| > (usher) ; returns 2
| > (usher) ; returns 3
| > (usher) ; returns "Sorry, sold out!"
| > (usher) ; returns "Sorry, sold out!"
| >
| > I am clueless about HOW to approach this problem.  I
can't
| > get past this issue: logically, I would expect that each
| > time a parameterless procedure was called then all local
| > variables inside its environment would be reinitialised.
I
| > am told it can be done - but have seen no code examples
that
| > show the technique.
| >
| > For me, this has been a really interesting issue of
scoping
| > variables - and at a guess, I'd say my problem lies in
where
| > I placed the variable needing to change.  Of course, I
am
| > most likely completely wrong :)
| >
| > Could someone kindly nudge me in the right direction?
|
| Yes, just do it as you say!  It's indeed a question of
scope.
|
|
| > My code is below.
| >
| > Kindest regards,
| >
| > Mike
| > ;--------------
| > ;This is what I have done (does not work):
| >
| > (define (usher)
| >   (let ((max-seats 3)
| >         (last-ticket 0))
| >     (if (equal? last-ticket max-seats)
| >         "Sorry Sold Out."
| >         (begin
| >           (set! last-ticket (+ last-ticket 1))
| >           last-ticket))))
| > ; Each time the procedure is called the value for
| > ; last-ticket is reinitialised to 0 and the result
always 1.
|
| So you know that when you put the variable inside the
function it gets
| reinitialized everytime you enter the function. Therefore
you need to
| put the variable outside of the function, as in:
|
|
| > ; This is a snap if the number of available seats was
| > external.
| >
| > (define seats 3)
| > (define next-ticket 0)
| > (define (usher)
| >   (if (equal? seats next-ticket)
| >       "Sorry, sold out!"
| >       (begin
| >         (set! next-ticket (+ next-ticket 1))
| >         next-ticket
| >         )))
|
| Or, if you want a local variable, use let, but put the
function inside:
|
| C/SCHEME[141]> (define usher (let ((seats 3)
|                                   (next-ticket 0))
|                               (lambda ()
|                                 (if (= seats next-ticket)
|                                     "Sorry, sold out!"
|                                     (begin
|                                      (set! next-ticket (+
1 next-ticket))
|                                      next-ticket)))))
| usher defined.
| C/SCHEME[142]> (usher)
| 1
| C/SCHEME[143]> (usher)
| 2
| C/SCHEME[144]> (usher)
| 3
| C/SCHEME[145]> (usher)
| "Sorry, sold out!"
| C/SCHEME[146]>
|
|
| --
| __Pascal Bourguignon__
http://www.informatimago.com/
|
| NOTE: The most fundamental particles in this product are
held
| together by a "gluing" force about which little is
currently known
| and whose adhesive power can therefore not be permanently
| guaranteed.
Hi Bear,

Thank you for taking the time to help - I really appreciate
it.

I just responded to Pascall - silly I know, but this is
exciting stuff.  I'd not have considered doing anything like
this at all ... to abstract perhaps.  But now that I see it,
it's as obvious as my nose on my own butt :)

I'm afraid I was unable to get your code to work - perhaps
my mistake.  I *think* I see where you are going with it
though.  Please correct me if I am wrong, (I was unable to
step through the code).  The inner lambda expression is
primed with the number of seats to start with.  However, it
seems that the code can only ever return 3, the inner lambda
expression is not applied.  And usher needs to be fed a
param that, irrespective returns 3. (usher "hello") ;==> 3.

I am very grateful for any help - and don't expect anyone to
solve things for me ...

I would have expected that the value 3 (in your code) IS
supposed to prime numseats.  Need to play with this to see
where it leads.  I really haven't used naked lambda
expressions all that much - and until now clearly I was
mistaken about how to exploit this.  Nothing has been lost -
rather, a whole load of opportunities have opened up that I
had never known existed until now.

This is really a fun language.

Kindest regards,

Mike

"Ray Dillinger" <b@sonic.net> wrote in message

news:4660dbee$0$27255$742ec2ed@news.sonic.net...
[....snip..]
| >
| > The problem: design a procedure called USHER that takes
no
| > params.  Each time it is called, it checks to see if
there
| > are any seats left.  If there are, the procedure returns
a
| > ticket number otherwise "Sorry. No seats left."  The
number
| > of seats must be contained inside this procedure - not
| > accessible to other procedures.
| >
| > Expected results:
| > (usher) ; returns 1
| > (usher) ; returns 2
| > (usher) ; returns 3
| > (usher) ; returns "Sorry, sold out!"
| > (usher) ; returns "Sorry, sold out!"
[.........snip.....]|
| Construct a function which, when evaluated, returns the
| function you want. Call that function with an argument
| giving the number of seats.
|
| Then, because the function you want is local to the
function
| that defined it, in lexical scope, it can see the argument
| of the function that created it.
|
| Here's a way.
|
| (define usher
|    (lambda (numseats)
|       (lambda ()
|           (if (<= numseats 0)
|               "sorry, sold out!"
|               (begin
|                  (set! numseats (- numseats 1))
|                  numseats))) 3)
|
| Now, the way you read this is:
|
| (define usher
|    (anonymous-function 3))
|
| Usher is the result of calling the anonymous function
| with an argument of 3.
|
| Not coincidentally, there's a form "let" defined for
| convenience that does this same trick.  In order to
| use it, you'd write:
|
| (define usher
|    (let ((numseats 3))  ;; let defines the anonymous
|                         ;; function from above and calls
|                         ;; it with argument 3
|       ... code for usher ...
|    ) )
|
| But I prefer using "lambda" to explain it because it's
| clearer what "lambda" does.
|
| Bear
|
|
|

Mike wrote:
> Hi Bear,
> I'm afraid I was unable to get your code to work - perhaps
> my mistake.  I *think* I see where you are going with it
> though.  Please correct me if I am wrong, (I was unable to
> step through the code).  The inner lambda expression is
> primed with the number of seats to start with.  However, it
> seems that the code can only ever return 3, the inner lambda
> expression is not applied.  And usher needs to be fed a
> param that, irrespective returns 3. (usher "hello") ;==> 3.

Oops, my mistake.  I shouldn't post code without testing
it, but sometimes I do.

Okay, here's what I meant to post.

  (define usher
     ((lambda (numseats)  ;;<== original version missed an
                          ;; open paren before lambda
        (lambda ()
            (if (<= numseats 0)
                "sorry, sold out!"
                (begin
                   (set! numseats (- numseats 1))
                   numseats)))) 3) ;; <== and closing paren
                                   ;; before 3.

As I look it over, I realize one thing: I have usher
return the number of seats remaining, whereas you
wanted a function that returns the number of seats
so far sold.

But you should be able to work this one out, right?
It just wants another variable, with the same kind
of scope as numseats, that keeps track of how many
seats sold.  So close over another variable, and you
should be able to fix it yourself. :-)

                                Bear

Hi Bear,

Thanks heaps!

This is the missing link - now my tool kit is getting truly
interesting :)  I learn lots by looking at code examples -
and then seeing what I can do with them.  I'm not quite
'there' yet in terms of evaluating the merit (efficiency) of
one approach over another.  For the moment, I do my best to
get a thing to work - then see if I can make it better.

And yes, I can take this and wreak loads of mischief with it
... all good of course.

Crystal clear code is always easy to follow.

Thank you again,

Mike

"Ray Dillinger" <b@sonic.net> wrote in message

news:466138c9$0$27198$742ec2ed@news.sonic.net...
| Mike wrote:

| > Hi Bear,
|
| > I'm afraid I was unable to get your code to work -
perhaps
| > my mistake.  I *think* I see where you are going with it
| > though.  Please correct me if I am wrong, (I was unable
to
| > step through the code).  The inner lambda expression is
| > primed with the number of seats to start with.  However,
it
| > seems that the code can only ever return 3, the inner
lambda
| > expression is not applied.  And usher needs to be fed a
| > param that, irrespective returns 3. (usher "hello") ;==>
3.
|
| Oops, my mistake.  I shouldn't post code without testing
| it, but sometimes I do.
|
| Okay, here's what I meant to post.
|
|  (define usher
|     ((lambda (numseats)  ;;<== original version missed an
|                          ;; open paren before lambda
|        (lambda ()
|            (if (<= numseats 0)
|                "sorry, sold out!"
|                (begin
|                   (set! numseats (- numseats 1))
|                   numseats)))) 3) ;; <== and closing paren
|                                   ;; before 3.
|
| As I look it over, I realize one thing: I have usher
| return the number of seats remaining, whereas you
| wanted a function that returns the number of seats
| so far sold.
|
| But you should be able to work this one out, right?
| It just wants another variable, with the same kind
| of scope as numseats, that keeps track of how many
| seats sold.  So close over another variable, and you
| should be able to fix it yourself. :-)
|
| Bear
|

"Mike" <mcu87@bigpond.net.au> writes:
> [...]
> Can you correct my thoughts on your approach?  Your code
> does not enclose usher in brackets - it doesn't need to
> because it contains a lambda expression which is the
> procedure applied when usher is called.  This explains WHY
> usher needed to be enclosed in brackets.

Actually,          (define (f arg...) body...)
is a shortcut for: (define f (lambda (arg...) body...))

>  However if I do
> this: (define foo (* 1 2 3 4))

And of course, apart from this shortcut, there's no difference in
scheme between function literals (lambda) and other literals such as
numbers.

> then foo is a constant

No, just a variable bound to some number at that time.

> (assuming I do not redefine it - bad technique). I cannot
> enclose foo in brackets any more than I could (10) -
> generates an error.  In both instances, the existence of
> brackets denotes that a procedure is to be applied - and
> instead of a procedure I gave foo (containing the value 24)
> and the numeric constant 10.  Is this correct?

Indeed.  In lisp, parentheses mean basically function _call_, so the
first item of the list must evaluate to a function (or be a syntax or
a macro).

> [...]
> Or is my thinking well off - as in, the lambda expression in
> your code is named and is called usher?

Yes.

What lambda produces is not a mere procedure, but a _closure_.  That
is, the free variables in the lambda expression are _enclosed_ into
the closure environment for the procedure to access them when it's
called.  In general, these free variables are found in the global
environment. But when they are lexical variables,  they're just
enclosed all the same, and the lexical scope is brought along with the
procedure, making an independant closure.

As indicated by Ray, you can create famillies of these closures,
writting a function to generate them:

(define make-usher
  (lambda (nb-of-seats)
    (let ((remaining-seats nb-of-seats))
      (lambda ()
         (if (< 0 remaining-seats)
            (begin (set! remaining-seats (- remaining-seats 1))
                    remaining-seats)
            "No more seats")))))

(define big-usher   (make-usher 10))
(define small-usher (make-usher 3))

(list (small-usher)  (small-usher)  (small-usher)  (small-usher)
      (big-usher)    (big-usher)    (big-usher)    (big-usher))

--> (2 1 0 "No more seats" 9 8 7 6)

;; Note: the result may vary depending on your implemenation.
;;       it could as well be:
--> ("No more seats" 0 1 2 6 7 8 9)

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

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc