On Nov 4, 2013, at 12:41 PM, Patrick Li patrickli.2001@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