[gambit-list] Two basic questions regarding the use of make-parameter and parameterize.

Marc Feeley feeley at iro.umontreal.ca
Mon Nov 4 13:50:35 EST 2013

On Nov 4, 2013, at 12:41 PM, Patrick Li <patrickli.2001 at gmail.com> wrote:

> > The closure in g remembers that p was bound to 222, and the closure in
> > h remembers that p was bound to 111.  So in the call (g 0) the result
> > will be 222 (i.e. 0+222), and in the first call (h 0) the result will
> > be 111 (i.e. 0+111).  What happens in the last expression?  The
> > parameter p is dynamically bound to 333, and then h is called. Because
> > h remembers that p was bound to 111, it reinstates this binding for
> > the evaluation of its body, (+ y (p)), so the result is 111
> > (i.e. 0+111).  So that's what I meant when I said "a calling function
> > can't use parameter objects to pass implicit parameters to the called
> > function".  The idiom (parameterize ((p ...)) (fn ...)) no longer
> > works for passing the implicit parameter p to fn.
> > 
> > Note that when parameter objects are automatically captured by
> > closures, parameter objects behave like lexical variables!
> > Consequently they would be completely redundant in the language.
> I understand now. Thank you for the in-depth explanation. Okay, I
> realize that I am asking for something slightly inconsistent. Do you
> have any ideas then how I could design a library interface to
> accomplish the following?
> Consider a library for managing stacks.
>    (make-stack)      : Create a new stack
>    (push stack item) : Pushes the item onto the stack.
>    (peek stack)      : Retrieves the top of the stack.
>    (pop stack)       : Pops off the top of the stack.
>    (empty? stack)    : Checks if the stack is empty.
> Usage of this library would be standard:
>    (define (make-random-stack)
>       (let [(mystack (make-stack))]
>          (push mystack 0)
>          (push mystack 1)
>          (store-random-callback
>             (lambda () (push mystack 0)))
>          (helper mystack)
>          mystack))
>    (define (helper s)
>       (pop s))
> It is annoying to have to thread the stack variable through the
> argument lists of all my functions. So I would rather have it passed
> implicitly. The (with-stack a-stack ...) command/macro tells the stack
> library that I would like all following push/pop/peek commands to
> operate on the given a-stack.
>    (define (make-random-stack)
>       (let [(mystack (make-stack))]
>          (with-stack mystack
>             (push 0)
>             (push 1)
>             (store-random-callback
>                (lambda () (push 0)))
>             (helper))
>          mystack))
>    (define (helper)
>       (pop))
> I feel that this is something reasonable to ask for, even though I now
> know that there is some inherent ambiguity (related to when and when
> not to capture) in the interface. 
> Thank you again for the in-depth explanations.
>   -Patrick

It seems what you really want is an implicit parameter for specific functions.  This could be achieved by the with-stack macro which would add the stack as the first parameter of calls to push, pop, etc in the body.  In other words:

  (with-stack <stack> <body>)

would expand into something like

  (let ((the-stack <stack>))
    (let ((push (lambda (item) (push the-stack item)))
          (peek (lambda () (peek the-stack)))
          (pop (lambda () (pop the-stack))))

Note the use of a plain inner "let" to create the specialized stack operations (a "letrec" would not work).


More information about the Gambit-list mailing list