Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Control flow - advanced mechanisms #5

Open
dumblob opened this issue May 18, 2021 · 5 comments
Open

Control flow - advanced mechanisms #5

dumblob opened this issue May 18, 2021 · 5 comments
Labels
enhancement New feature or request

Comments

@dumblob
Copy link

dumblob commented May 18, 2021

All languages need some form of "escaping the structured programming fences". Older imperative languages have goto for this, but newer ones try to find some safer alternatives. Here is a (non-comprehensive) list of things to consider as it seems Til doesn't yet have a stabilized polished way to cover all the "escape structured programming use cases".

  • exceptions (currently error and error.handler procedures)
  • yield (a "highly tamed" form of async/await; untamed forms I personally dislike for objective reasons)
  • trap (as from bourne shell) or alike
  • Koka's effects on steroids (similar in capabilities as exceptions in Dylan; i.e. combining exceptions as they're now in Til plus yield - i.e. resumption)
  • V's ephemeral (!) optionals (I love them - but they require special syntax support and distinction between compile-time and run-time; but they completely avoid introducing none/null/nil value to the langue which is a huge advantage as three-state logic proved to be one of the few worst things in the whole IT industry)
@cleberzavadniak
Copy link
Contributor

I tend to favor Actor Model, so I believe exiting the process immediately and signaling the "linked" ones would work fine where error is not exactly applicable.

@cleberzavadniak cleberzavadniak added the enhancement New feature or request label May 20, 2021
@dumblob
Copy link
Author

dumblob commented May 20, 2021

Isn't the Actor Model rather expensive in practice (both performance-wise as well as code-bloat-wise)? If you have any specific API in mind, go ahead - I'm all ears to see and contemplate 😉.

@dumblob
Copy link
Author

dumblob commented May 20, 2021

If we decide to pursue something like those processors I outlined in #8 (comment) then we might enforce every processor to get (and thus to handle) an "interrupt channel" akin to "interrupts" physical CPUs have.

It's much less intrusive than trap in shell, but encourages/forces one to handle it. We could also provide some "default" handler which the user could just stick in - we could even provide more such handlers depending which behavior we want to model - sometimes one would want to model bourne shell's trap, sometimes something like an exception from outside or even from processor's own Til code, etc.

This way it'd be easy to construct other abstractions - including effects, exceptions, traps, yields, etc.

Hm, asking myself why I didn't get this idea anytime before? Thanks for allowing me to brainstorm it here! Need to go breathe some fresh air... 😉

@cleberzavadniak
Copy link
Contributor

I was thinking about sending a "common" message to the calling process / spawner but that would require both handling priorities in the queue and would force the programmer to handle some exceptional behaviors together with common routines, so I thought about something more or less like error.handler - it should interrupt the normal flow but would be allowed to change values in the scope. Not sure about how "safe" that would be and that's why I would rather shove everything into receive, probably, and implement common behaviors Erlang-style, like supervisors processes.

(But I also hate the possibility of letting errors go unnoticed, so that's indeed something to think very carefully.)

@dumblob
Copy link
Author

dumblob commented May 20, 2021

probably, and implement common behaviors Erlang-style, like supervisors processes.

This is actually the thing I'd rather get rid of (that's one of the reasons why I described "processors"). There are 2 reasons - first, the parent needs to always implement some restarting behavior which is tedious ("processors" guarantee "reentrancy" so can be spawned by a third-party in many instances if channels will get correctly muxed/demuxed) and error-prone because it makes "everything connected to everything with no overall boundaries" (it's kind of "distributed too much" 😉). Second, it encourages thinking of processes (and thus designing the whole application as such) as something which begins here and ends there. Dot. Done. That's actually not what happens in practice - most "processes" are long-running self-contained entities.

But if the language provides only a low level primitive like a one-off process, then all the "process-instance-specific loop with select/poll/... etc." has to be implemented over and over yourself which has following downsides: slow & difficult to optimize (because programmer has too much free hands), more error prone (again, too free hands), verbose (Til shall be IMHO terser than this approach would offer).

On the other hand, I might be misunderstanding and imagining something different than you in which case I'm eager to see what you'll come up with 😉.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants