Federico Pereiro
01/09/2025, 10:03 PMJimmy Miller
To summarize our point so far: consistency issues arise when we attempt to respond to multiple calls in parallel, that is, instead of responding to one call and then to another call, and there is some shared data concerning both calls that is modified by one of the calls.You can have inconsistency with complete serial calls if you just have a lossy communications medium. This is the most common problem I see with inconsistency in practice. X sends Y a message and unknown to X, it failed on Ys side. There are lots of results about consistency (CAP, CALM etc ) and practical things like Jepsen.
Andrew F
01/09/2025, 10:43 PMDuncan Cragg
01/10/2025, 12:14 AMDuncan Cragg
01/10/2025, 12:29 AMDuncan Cragg
01/10/2025, 12:37 AMFederico Pereiro
01/10/2025, 9:00 PMFederico Pereiro
01/10/2025, 9:01 PMFederico Pereiro
01/10/2025, 9:02 PMFederico Pereiro
01/10/2025, 9:03 PMMicrocode could be seen as a declarative interface to a CPU ("I tell the CPU what operation I want and let the CPU actually manage its own logic gates"). Similarly, a line of a very high level program might be seen as imperative ("give me all the rows from this database where the creation time is less than three seconds ago"). I propose that we eliminate this distinction- In other words, at every level the outside of the call is declarative and its logic is imperative. There's no hard absolute line that says "above this, it's all declarative"; our understanding of it is self-similar, fractal, working at every scale in the same way. - Rather than try to convince you, I'd really like to understand why/how you see that a model based on calls is inherently imperative; and perhaps more importantly, whether declarative operations (when they are requested, not when they are implemented) cannot be modelled themselves as calls. I promise to keep an open mind! - I just discovered your work on Onex. It seems we're both in love with the spreadsheet! Cell too is a programming model based on the spreadsheet. Really cool that you're working on that direction!
Federico Pereiro
01/10/2025, 9:03 PMJimmy Miller
Concerning your point about bottlenecks, I am referring to the conceptual burden of designing and implementing a system, where human brains (not computer performance) seem to be the limiting factor of the speed of development.All the systems I've worked on where human brains were the bottleneck, I don't think would get 10x faster with this (as far as I understand it process). But all the system I can think of where human brains are the bottleneck might not meet your definition of DIS (compilers for example).
Behind this (and I just put this in the Programmers' Preface) is that if many of us feel in our bones that easily 90% of software is pure accidental complexity (in the Brooks sense), then a 10x leap can come through by finding a way to drop this baggage with better tools (both conceptual and embodied).My reading of Brooks (see the episode for more) is that he was concerned with industrial scale 10x improvement. That companies can actually produce software 10x faster. I guess that's what I had in mind.
This is akin to the second non-parallel source of inconsistency I mention: Not checking for errors in multi-step sequences.; the lack of acknowledgment from Y to X is to me exactly equivalent to a sequence happening in a single node that doesn't stop when an error happens in the middle.The problem is, in a lossy communications channel, it is impossible to check for errors. Acknowledgements don't solve the problem. Because how do I know the person who sent me the message got my acknowledgement? The two generals problem illustrates this well. But it goes deeper than that two. Being distributed makes a huge difference in the kinds of failures you can have. For example, it has been proven that it is impossible to tell the difference between a node taking too long and a node that has crashed if you have even one faulty node I don't want this all to come across as over negative. I love people creating these high minded general approaches. Even if I don't agree with any of them in particular, I think it is good to think through and have this kind of thinking for people to contrast with. If you haven't seen his work, I'd definitely recommend some talks from Peter Alvaro. He's got one on writing software with an order of magnitude less code using a datalog derivative. Shares some of the squashing of call vs remote that you are interesting in. (But with explicit time.) and he's got another on persistent memory and a globally singular dataspace (The whole world has one dataspace)
Andrew F
01/10/2025, 9:27 PMDuncan Cragg
01/11/2025, 12:10 AMDuncan Cragg
01/11/2025, 12:16 AMDuncan Cragg
01/11/2025, 12:22 AMDuncan Cragg
01/11/2025, 12:28 AMnull, it can be represented by the absence of a certain key in a hash; but inside a list, it has to be represented with something else, such as the text null or an empty string." - I have two special concepts for unspecified values: unknown (could be anything but isn't set yet) and nothing (known-to-be-absent or is definitely not going to be set). Or not available vs not applicable. Setting a hash or map property to nothing deletes that property. setting a list value to nothing deletes that entry in the list.Duncan Cragg
01/11/2025, 10:03 PMDuncan Cragg
01/11/2025, 10:24 PMAndrew F
01/11/2025, 10:29 PMFederico Pereiro
01/12/2025, 2:20 PMFederico Pereiro
01/12/2025, 2:20 PMFederico Pereiro
01/12/2025, 2:21 PMFederico Pereiro
01/12/2025, 2:29 PMAndrew F
01/12/2025, 3:49 PMDuncan Cragg
01/13/2025, 11:07 AMFederico Pereiro
01/13/2025, 4:43 PMThe characteristic feature of the tagless-final approach is extensibility: a DSL expression, once written, can be interpreted in a variety of ways -- to evaluate, to pretty-print, to analyze, to transform or compile. At any time one may add more interpreters, more optimization passes, and even more expression forms to the DSL while re-using the earlier written DSL programs and interpreters as they are. Perhaps counter-intuitively, the tagless-final style supports DSL transformations: from reduction, constant propagation and partial evaluation to CPS transformations and loop interchange.This is powerful. And I totally consider a DSL to be data. If I understand it correctly, this approach allows you to write code at a high level of abstraction and then let it be transformed into a shape that carries a lower level implementation (generic programming), without affecting the high level specification. The paper says that this is better than abstract algebraic types, but that goes over my head. In your view/experience, what makes this approach so powerful?
Federico Pereiro
01/13/2025, 4:45 PMDuncan Cragg
01/13/2025, 5:30 PMDuncan Cragg
01/13/2025, 8:30 PMFederico Pereiro
01/13/2025, 9:19 PMGuyren Howe
01/13/2025, 9:21 PMFederico Pereiro
01/14/2025, 8:36 AMGuyren Howe
01/14/2025, 5:28 PMDuncan Cragg
02/10/2025, 10:07 AMFederico Pereiro
02/16/2025, 7:56 PMtemperature C 20
F 68
Now, how could we actually update it?
temperature C 20
F 68
update : m 1 if cond = 1 @ m unit
2 C
then 1 @ set dest C
value @ m degrees
2 @ set dest F
value + . * . @ m degrees
. 1.8
. 32
else 1 @ set dest F
value @ m degrees
2 @ set dest C
value * . - . @ m degrees
. 32
. / . 5
. 9
2 C @ C
F @ F
@ update degrees 60
unit C
= C 60
F 140
Now, am I cheating by having a separate update function? Or disappointing you? Probably both! 😅
Yet, in a spreadsheet, you cannot just have one formula referencing another and then the second formula referencing the first one.
What would make it more declarative is to be able to bind a change event (like I do in the JS version) so that if someone puts temperature C or F, it will invoke directly temperature update. Perhaps something like:
@ listen call @ put
path @ temperature C
then call @ temperature update
message degrees @ temperature C
unit C
@ listen call @ put
path @ temperature F
then call @ temperature update
message degrees @ temperature F
unit F
The repetition above is making my eyes ache and giving me fever visions of a macro system. You're definitely taking my car and driving it through rocky terrain here.Duncan Cragg
02/18/2025, 1:10 PMDuncan Cragg
02/19/2025, 11:41 AMDuncan Cragg
02/19/2025, 11:43 AMFederico Pereiro
02/22/2025, 9:03 PMtemperature. C and F are just numbers, representing the temperature, each in its respective unit.
- We also store update inside temperature, which is a function that takes a hash with keys temperature and unit as input.
- update, when getting called, makes the updates to temperature C and temperature F, taking care to convert C to F or F to C.
- The listen calls put listeners that, when temperature C or temperature F are updated, then goes and call temperature update. In that way, you don't have to call temperature update explicitly.
- The listen calls are unidirectional, but there are two of them (one for each unit).
- As for id-able object, you would expose your data explicitly through http. For example:
@ http server route method get
path /temperature
handler C @ temperature C
F @ temperature F
- If the cell server was hosted at <http://example.com/cell|example.com/cell>, then by calling GET <http://example.com/cell/temperature|example.com/cell/temperature> you could obtain a hash (as JSON, stringified) with both temperatures. In a more involved way (that I won't dare type now) you could also invoke temperature update through a POST request. I don't see necessarily a necessity for ids imposed system-wide, you choose how to expose your cell (through HTTP or other methods).
- A response could keep responding, indeed, but HTTP doesn't allow for this, you'd have to keep on polling. In websockets, it could work. The TODIS paradigm does a call to update its response.
- I love the example challenge! However, cell is right now not able to compute even a sum. I'll definitely have it in mind as an example when we have a base system going.
Thanks for the interest!Duncan Cragg
02/24/2025, 2:44 PM