> On Aug 3, 2018, at 15:36, Alexis King <lexi.lam...@gmail.com> wrote:
> 
> Maybe this isn’t really a direct response to the direction this thread
> has taken, but given the question proposed in the original message, I
> think it’s relevant to share a particular design pattern for parameters
> that seems to work well. In a number of different APIs provided by
> Racket, a function’s behavior can be controlled by an optional argument
> (often a keyword argument), and that argument’s default value is the
> value of a parameter. For example, the eval function accepts an optional
> namespace as its second argument, and if it isn’t supplied, it uses
> (current-namespace).
> 
> From a user’s point of view, this is the best of both worlds, since they
> can parameterize a set of function calls in a single parameterize block
> without needing to thread an argument everywhere, taking advantage of
> parameters’ capability for implicit configuration, but they can also
> pass an argument directly if they’re only calling a function once or
> twice. However, this *also* has benefits for implementors, since it
> sidesteps the inability to close over the value of the current
> parameterization since the value becomes entirely lexical when it is
> bound to the formal argument of the function.

This makes perfect sense to me, but it doesn’t alleviate the pain of having to 
thread the lexical arguments through all nested function calls; I claim this is 
somewhat orthogonal to my question.

Then again, you did mention that this wasn’t a direct response to my question 
:).

John


> For a simple example, consider a contrived function configured by a
> parameter:
> 
>  (define current-summand (make-parameter 0))
> 
>  (define (make-adder)
>    (lambda (n) (+ (current-summand) n)))
> 
> This is a silly function, but one can see how it is broken in the way
> Alex describes (which he shows can happen in more realistic situations).
> The intent is to close over the current value of (current-summand) when
> make-adder is invoked, but a naïve implementation doesn’t capture the
> current value and always produces the same function. Adjusting this
> function that the summand is provided as an optional argument both
> improves the user-facing API and fixes the bug:
> 
>  (define (make-adder [summand (current-summand)])
>    (lambda (n) (+ summand n)))
> 
> This also ensures that if a parameter-configured function defers to
> other functions as part of its implementation, it will pass the value
> lexically rather than dynamically by explicitly providing the optional
> argument, so the dynamic configuration is effectively “terminated” at
> the API boundary.
> 
> Now, this isn’t to say this technique doesn’t have some drawbacks. For
> one, it means API users get to benefit from the dynamic configuration,
> but API implementors do not, and in fact have to do extra work.
> Furthermore, one might find the very existence of a “design pattern” in
> Racket to be suspect, given we generally try to avoid boilerplate
> patterns in favor of new linguistic abstractions. Maybe this hints at
> some shortcoming in parameters that would be better solved by a new
> language feature, but I can’t immediately come up with one. Perhaps
> others have better ideas than I do in that department.
> 
>> On Aug 2, 2018, at 12:24, 'John Clements' via Racket Users
>> <racket-users@googlegroups.com> wrote:
>> 
>> I hate to turn a little question into a big one, but… are parameters
>> the right choice, here? It seems to me that optional parameters would
>> be more suitable.
>> 
>> Unfortunately, I’ve been on the other side of this fence, too:
>> parameters are vastly more convenient for implementors than adding
>> optional parameters to every one of the internal calls. This certainly
>> came up for me in the construction of a CSV writing library.
>> 
>> I can imagine a bunch of programming patterns that might assist this;
>> the most obvious one would be an object-like metaphor where parameter
>> values are represented as an object to which calls are made. Do others
>> have ideas on a “best practice” for this situation and others like it?
>> 
>> John
> 



-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to