I am quite interested in Event Handlers. In colle...
# thinking-together
g
I am quite interested in Event Handlers. In college, I remember in my languages course discussing how you could have static scope or dynamic scope — whether a non-local identifier is searched for in the scope where the thing being called was defined, or in the scope where it’s being called. Static won out, because in general it’s easier to reason about. I mention all this, because I think I understand what Event Handlers are and how they work, and afaict, they’re just “a thing with dynamic scope”. That all seems fine and good, but I never hear EH being described that way. Maybe because folks have forgotten about dynamic scope?
j
I think you’re talking about (algebraic) effect handlers, not event handlers. Otherwise, I’m not sure what “event handler” refers to.
d
yeah I'm struggling with this, but it sounds interesting... do go on...
g
Yes: Algebraic Effect Handlers. My bad.
j
(FWIW, based on my limited understanding, I agree that effect handlers are dynamically scoped. Some related things in the modern world that use dynamic scoping: dependency injection, Scala’s ‘implicits’.)
g
Nice observation.
j
Many algebraic effect systems are indeed dynamically scoped, but there are also others (like Effekt, https://effekt-lang.org/) that use lexical effect handlers (regaining the simpler reasoning you usually have with lexical / static scope).
This paper (from the Effekt lead) compares dynamic vs. lexical effect handlers, along with other aspects. Might be good to read: https://link.springer.com/chapter/10.1007/978-3-030-83128-8_3 (It should be open access, if you can't access it, let me know.)
j
@J. Ryan Stinnett Thanks for the pointer! Section 4.1 in that paper is really clarifying to me. I think some of my understanding of this static/dynamic scope stuff has been off. I’ve thought of Scala implicits as dynamically scoped, because implicitly passed parameters to a function are passed on to things called in the function. But this sense of “things called in the function” is actually lexically defined, not dynamically defined! That is, if you define a closure in your function’s body, you pass implicit parameters to functions called in the closure – this binding can’t be intercepted by functions that end up on the call stack between the two functions. This is perfectly analogous to the situation described in Section 4.1. So there’s some mechanism working here that I’ve always thought of as “dynamic scope” even though it’s really just “lexical scope implicitly propagated through function calls”. I think real dynamic scope is something you couldn’t resolve at compilation time, but all of these things (Effekt’s handlers, Scala implicits) are statically resolvable. Hmm! (Looks like Effekt was previously implemented as a Scala library: https://www.cambridge.org/core/services/aop-cambridge-core/content/view/A19680B18FB74[…]_type_and_effectsafe_extensible_effect_handlers_in_scala.pdf)