[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?
>
> EXPLICIT PARAMETER PASSING:
>
> 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))
>
> IMPLICIT PARAMETER PASSING:
>
> 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))))
<body>))
Note the use of a plain inner "let" to create the specialized stack operations (a "letrec" would not work).
Marc
More information about the Gambit-list
mailing list