Call Return Spaghetti
2024-08-18
PAUL TARVYDAS
AUG 19
In the essay referenced below, I examine why a diagram of a Call/Return system makes less sense than a diagram of a concurrent system.
Call/Return operates in a LIFO - last-in first-out, stack-like - manner.
Adopting an alternate perspective - FIFO, first-in first-out, queue-like manner - allows us to represent diagrams more easily.
CPU chips implement CALL and RETURN instructions as single opcodes, but, they do not implement queue behaviour as single opcodes.
Most popular languages are generally function-based, e.g. C, Haskell, Python, Javascript, Smalltalk, etc. Such function-based languages tend to adopt a LIFO (callstack) perspective and tend to use CALL and RETURN opcodes to fake out the function-based paradigm.
Such languages allow programmers to implement FIFO queues, but, such languages encourage the use of LIFO stacks. This seemingly small difference subtly affects designs with function-based - stack-based - thinking. This difference ultimately encourages single-threaded design while making multi-threaded design more difficult to imagine and to implement, as witnessed by the fact that most languages relegate multi-threading to hefty code libraries, while treating functions as basic building blocks.
This subtle encouragement towards function-based thinking has led to the general impression that Visual Programming Languages (VPLs), node-and-wire Diagrammatic Programming Languages (DPLs), Actors, etc., are ineffective programming tools.
I argue that VPLs, DPLs, Actors, etc. are effective programming tools, but that their use is are ultimately discouraged by the over-use of the function-based paradigm.
Further
One thing I've tried to articulate to you in the past, might be worth trying again:
LIFO has one advantage over FIFO as you implement it so far in your projects:
- call/return involves passing arbitrary numbers of values between a single producer and a single consumer (caller/callee).
- FIFOs involve passing arbitrary numbers of values between multiple producers and a single consumer (or vice versa)
I think the single/single constraint is easier to reason about. FIFOs might be easier to program with if you somehow preserve that constraint. It would certainly eliminate at a stroke a bunch of corner cases of timing and synchronization that bother me every time I think about your stuff.
One way to achieve this would be to say the nodes in the VPL can only have a single input port, but that port can take on arbitrarily structured types (records, arrays, etc.). Then you'd simulate multiple ports using tuple types, but the tuples would have to be explicitly created in a single node at a time.
Another way would be to restrict fan-in or fan-out somehow. Either input ports or output ports can only connect to a single wire. (I work at recroom.com, and our VPL includes both the input and output constraints in different situations. Might be worth a look: blog.recroom.com/posts/2021/5/03/the-circuits-handbook.)
What is your opinion of Go?
Multi-threading is much more fundamental to the language (and lighter weight). Part of that is how it manages the stack memory for each thread.
(Disclaimer: I don't know Go very well).
(xpost from substack) What I am hearing is that dataflow notebooks, like ObservableHQ in my case, are a bit of an unholy matrimony between the two styles. FWIW I've been using their 'Runtime' dispatcher as a set of training wheels, given my heavy functional-programming bias. But my experience has been that important quality-of-life tools (map-reduce pipelines) that rely on the call stack are inherently hard to debug under the event-driven paradigm. And this seems to be the kernel of that idea.
Yeah works for me just now.
(I didn't actually click on it this time because I've read it before π )
I also got the 404, it's because a .
is postpended to the URL. My best guess is that Slack on Windows -> Firefox behaves differently than Kartik's setup. This one works for me:
Ha, I totally misinterpreted which blog link we're talking about. Paul's blog link works fine for me, my recroom link does not. Unfortunately I can't edit that comment anymore.
At least Slack is consistent across platforms.
What is your opinion of Go?
I have strong opinions about how to structure component-based programs while retaining both, FIFOs and LIFOs. 0D is but one manifestation of these opinions. Golang comes closer than most other languages but is more like an assembler for component-based programming rather than a structured way to compose component-based programs. ...
@Jasmine Otto do you have a suggestion on how I might get a 50,000 foot overview of ObservableHQ and the 'Runtime' dispatcher?
Paul Tarvydas Yes! They've been shuffling their docs around, especially for the Framework release, so I really hope these don't get lost.
syntax - observablehq.com/documentation/cells/observable-javascript
dispatcher - observablehq.com/@observablehq/how-observable-runs