3 ms·
> Most third-party code will be unable to forward a `context` argument to a callback Having a context argument which is passed to the callback has been par for
by magicalhippo 2y ago
> Most third-party code will be unable to forward a `context` argument to a callback
Having a context argument which is passed to the callback has been par for the course in all cases I've seen, but I've mostly been in C land and related areas.
Though, if you have closures, should you still prefer a context param?
> If JavaScript had this feature, the syntax for defining and calling functions would be the same, no matter whether you're dealing with a normal function, a generator, or an async function.
How would one reason about performance and possibly concurrency in such languages?
- fleabitdev 2y agoIn a language with algebraic effects, questions like "how should I make this `CancellationToken` available to these forty small functions?" simply go away :-) It's ambient state, just like a `catch` block, and so you can make it ambiently available to a whole tree of function calls. The outcome is the same as passing around a context argument by hand, and it can have equally strong type-checking, but the compiler handles all of the boilerplate for you. To answer your second question: I agree that, in a dynamic language like JavaScript, making all of these language features implicit could be too costly. I'm more optimistic about effect systems in statically-typed languages.
- magicalhippo 2y ago> ambiently available to a whole tree of function calls So a "localized global variable" of sorts? Sounds interesting, got any links to examples I could look at?
- fleabitdev 2y agoThe term is "dynamic scope": https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope_vs._dynamic_scope https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexic... It isn't a very common language feature, but you could take a look at React's `Context` or Common Lisp's `defparameter`.
- magicalhippo 2y agoAh, like Python objects then. Which is unfortunate, because that's one of my main dislikes with languages like Python. I was imagining more along the lines of (on-the-spot pseudo-code) using [x := foo(...)] { bar(); output(); } func bar() { x = x + 1 } where bar() and output(), or something they call in turn, can reference x and it would be a compile-time error to use bar() or output() in cases where they couldn't resolve x. Or something more along those lines. Anyway, cheers, always fun to ponder these things.
- fleabitdev 2y agoSorry, the Wikipedia article isn't very helpful. Your example is the correct one. The killer feature is that you can shadow a dynamic variable, changing its value for the duration of a dynamic scope, in the same way that an inner `catch` handler overrides an outer one. For example, you could have a dynamic variable which tells the `print` function where to send its text output. The variable's value would probably default to stdout. By temporarily assigning a string-stream to that variable, you could collect an arbitrary function's text output into a string instead. Regardless of where the text is going, any function which produces text could still use the convenient global `print` function.
- magicalhippo 2y agoRight. The closest thing I'm familiar with is the dynamic context used in Serilog[1], where you add log properties to the current scope, which gets added to each log line generated in that scope, and removed once the scope exits. Of course, no compile-time checking there, so the combination sounds indeed quite useful. https://github.com/serilog/serilog/wiki/Enrichment#the-logcontext https://github.com/serilog/serilog/wiki/Enrichment#the-logco...