Hi John,
1) Delve into dynamic and fluid variables
On Mon, 9 Mar 2020 at 00:39, John Cowan cowan@ccil.org wrote:
On Sun, Mar 8, 2020 at 11:17 AM Adam adam.mlmb@gmail.com wrote:
For completeness can you please provide some reference URL to the latter
two or/and describe very briefly?
For fluid variables, see the withdrawn SRFI 15, < https://srfi.schemers.org/srfi-15/srfi-15.html%3E. Dynamic variables are an equivalent Common Lisp concept. Fluid and dynamic variables behave like global variables that have been bound permanently to a parameter, so they are accessible from everywhere and can be parameterized anywhere. In Common Lisp, all top-level variables (but not constants or functions) are dynamic, and conventionally are written with an asterisk as a prefix and suffix. In addition, when a variable in a Common LIsp lambda-list (or equivalent) is dynamic, it will be parameterized rather than lexically bound when the procedure is called.
* Are you saying that "Fluid variables" (SRFI 15, withdrawn) is a Scheme port and equivalent of "dynamic variables" in CL?
* If you have a reference to the dynamic variables section in some CL implementation's docs feel free to share.
* The fluid variables implementation in https://srfi.schemers.org/srfi-15/srfi-15.html looks expensive:
Accesses to a fluid variable have no additional overhead over normal variable accesses, but a constant "switching cost" is incurred for each fluid variable you have, at continuation jump time.
This implementation's worst-case overhead is incredibly large. (That is with high number of continuation jumps, high number of fluid variables, and few or no actual fluid variable accesses.)
I think compared to this one I prefer the current Gambit parameter object overhead profile: |parameterize| and load/store have overhead, but there is no switching cost.
* (The fluid variables impl would not work out of the box in Gambit, as Gambit apart from normal continuation jumps, has low level continuation jumps from the green threads which are outside |dynamic-wind|'s scope.)
2) Briefness of syntax
All the examples I have found (except Marc's, thank you Marc) involve using
parameters in exactly this way, which I why I am especially interested in other use cases.
There is a problem with parameters: if a procedure implicitly depends on a parameter, and you want to use the procedure in a "localized" way, then binding the parameter around the whole or a substantial part of a program is convenient. But to use such a procedure in a "universal" way independent of its context, it is necessary to wrap *every* call in a parameterize expression.
Agreed. This is fine. If typing out (parameterize ((parameter-object value) …) (procedure …)) over and over would be a problem, a shorthand syntax could be devised e.g. (§ parameter-object: value procedure …) , implementable as a macro.
3) Faster ways?
* Did you have a thought with bringing up fluid/dynamic variables, to make a point along the lines that significant cost reductions to parameter objects may be possible, for a slightly narrower definition of parameter object?
* I'd be curious if a "global fixed parameter object" could somehow be made to avoid btree/hashtable lookups. Wildguessing, having a vector allocation or copy at |parameterize| should be fine shouldn't it, and also having the first parameter object load/store operation within a |parameterize| _only_, do some kind of punch-through resolve, should be fine also shouldn't it.
Anyhow luckily computers are fast and getting faster, btree/hashtable structures for a couple hundred elements should tend to fit in the L1 cache.
Looking forward to his benchmarks later.
Thanks again for taking on the conversation. Was curious about the performance overhead because I find them so useful per the previous teleport hr example.
Best regards, Adam