I like that the code example seems to indicate they took the concept of "ports" from flow-based programming, which might be one of it's absolute strongest points:
That is, enabling data flow connections between individual inputs/outputs, and not just between components, which otherwise is too limiting, and typically causes a lot of extra syntax to handle that routing otherwise.
That aside: really cool article! Dataflow just pops up everywhere as a really, really useful abstraction, and our languages don't support it well as a general mechanism.
Instead we tend to have specialized dataflow-y tooling for one area of programming where the advantages are so significant that the impedance mismatch is worth it nonetheless.
I think you are right, and I should have done a search on that before. Found now that FBP inventor cites someone Weinberg from 1975 about them (though FBP is supposed to be from around 69-70, so might be a somewhat parallel discovery):
> Now what are "IN" and "OUT" that our pseudocode receives IPs from and sends them to? They are not the names of connections, as this would tie a component's code to one place in the network, but are things called "ports". "Portae" means "gates" in Latin, and ports (like seaports) can be thought of as specific places in a wall or boundary where things or people go in or out. Weinberg (1975) describes a port as
"... a special place on the boundary through which input and output flow... Only within the location of the port can the dangerous processes of input and output take place, and by so localizing these processes, special mechanisms may be brought to bear on the special problems of input and output."
Still, I'm amazed at how it took so long before they became mainstream in data flow oriented libraries and DSLs.
And it seems J.P. Morrison was also highlighting Named ports as particularly useful, which is also perhaps what I should have highlighted in my initial comment above.
It's gotten better lately it seems, but a lot of tools skipped that part, which now requires tons of specialized syntax just for routing of multiple parallel streams.
I'm not trying to be pedantic, but they're different words, and (esp. considering how capable our community is when it comes to logic and precision with programming languages) I find it strange how often this "it's / its" error is repeated. Calling it out in hopes of helping others get it right.
There's nothing strange about how often this error is repeated. It is a fault in the "design" of the English language, which violates its own rules, insofar as it has any. Apostrophes are used for both possessives and contractions, eg. "That's John's ball". Indeed possessive "it's" was historically written with the apostrophe. That the apostrophe was dropped to become possessive "its" is completely arbitrary special-case logic, and given that there is no logic behind which it was dropped from, it is easily subject to confusion because you cannot reason about which is which if you forget in the moment.
Yea, I think I kind of know this in theory, but tend to mix them up sometimes as a non-native English speaker. Good to try to iron out those common mistakes though for sure.
I don't really understand what problem this is meant to solve at first glance. It'd be nice to see a simple example program involving concurrency written in plain Python, then a discussion of the annoying bookkeeping involved in avoiding concurrency errors and what traps would be easy to fall into, and then an example of how the same thing would be implemented using Lingua Franca and an explanation of how eliminates the bookkeeping and traps.
Can you explain what the examples are showcasing? I looked at the Audio and Webserver examples. They give the LF syntax for doing something that is easier to do directly in Python. I'm missing the advantages of LF and why you'd want to do this in the first place.
I think the main example on the landing page is a bit counterintuitive?
Rock Paper Scissors but the graph presents the reveal as a reaction to the observation? In a loop? And somewhere there's a min-delay of a magical 1 sec? Why 1 sec and not 0.1 sec? Can this build up and the players get out of sync? (A bit strange to 'just wait, lol' if the language aims at solving problems in distributed systems).
Overall the example would be better if it separated the game from the players and also split out the repeat loop.
Maybe let both player reveal to a host and then receive a result (and the choices) ~ This way both players can be sure that the choice of the other player is independent of the observation.
(I know that the example is 'correct' in that the choice is made independent of the observation but I think the example could be improved if it solved some of the coordination problems involved in the scenario more cleanly through code architecture).
Overall I quite like the idea of having this polyglot meta language!
If you like the idea and work in robotics try out copper-rs, it works on the same underpinning concept but at compile time in rust + a graph description.
The latest addition to the kernel is a profile guided scheduling feature that allows you to optimize the concurrency of the graph still at compile time based on previous timing measurements from its deterministic logs.
The main thing this seems to provide is determinism. Where Erlang, to stick to your question, can be non-deterministic (without taking special care). I'm reading the dissertation this work is based on to see how it guarantees determinism, so at present I'm just taking their word for it.
In chapter 1 they provide an example of (using Erlang syntax, completely untested so probably needs some massaging to run as I'm rusty on Erlang) this scenario, which would be deterministic in Erlang:
Because messages sent from one process to another are guaranteed to be made available in that same order, this is deterministic. They introduce a motivating example on page 5 (21 in the PDF) where a relay is introduced.
relay() ->
receive
P -> P ! dbl
end,
relay(P).
main_with_relay() ->
P = spawn(counter),
R = spawn(relay),
R ! P, % <- trouble starts here
P ! {inc, 1}.
This may give the same result as the first example when run on the same node, but the guarantee is lost, it might not happen in the same order as the first version. For an example where it will likely give a different result, consider if counter were a local process to main (on the same node) while relay were a remote process (on a separate node) with high latency, it's likely that the network delay would result in {inc, 1} arriving before dbl.
The work in LF lets you write this (don't ask me how, still reading) so that the relay would be logically instantaneous even if physically it wasn't, consequently the dbl message would arrive "first" by logical time and the counter would process things as in the original Erlang code.
Of course, you can make the Erlang relay behavior deterministic, but you have to add extra code to achieve it. LF apparently gives you a simpler way to get the desired determinism without having to write the extra code yourself, it's baked into its semantics.
It appears to be deterministic in a static structure. If your program adds and deletes actors, then LF has problems. It tries to get around this with modes.
Sim-Diasca is an Erlang simulation system that implements the superdense time step mechanism used in LF via distributed time managers and a global barrier which gives repeatable results.
This project lacks a compelling sales pitch. It mentions that LF is better than actors but I also don't see no reason to believe that.
It does offer a deep dive into what reactors are but why would I bother to learn? If OP reads my comment, that's what I would add to this landing page. Show me why the alternatives mentioned are inferior.
I wonder, if there is so long research, why you have not come to conclusion that the main problem is not reactor/proactor/event loop, but writing actual asynchronous business logic. The industry has gone mostly coroutine approach, requiring special technology support and usually with lack of fine predictable execution and stack control for mission-critical cases.
That's the reason why FutoIn AsyncSteps exists as concept and reference implementation in C++, Java and JS/ECMAScript. It is compatible with foreign reactors by design via AsyncTool interface.
Your use of the word "Reactor" at first confused me since there is a "Reactor Pattern" for event handling (https://en.wikipedia.org/wiki/Reactor_pattern) which is not what you mean.
How does your concurrency model differ from that of Erlang (the poster child for distributed concurrency)? Do you have a paper detailing your model and comparing with other languages?
I recently read Roman Obermaisser's excellent book "Event-Triggered and Time-Triggered Control Paradigms" which seems applicable to your architecture. At the bottom most level you have a global communication network based on a synchronized global clock and "Time-Triggered"(TT) semantics which is deterministic. A "Event-Triggered"(ET) communication channel is then overlaid on top of it which is non-deterministic. That way the system provides both hard real-time (i.e. TT) and soft real-time (i.e. ET) semantics.
Title is incorrect of course, it is: "Intuitive concurrent programming in a separate language than the one you use for the actual work"
... which is not to say it's irrelevant, but still: Why is it worthwhile to have a separate language for this, rather than some library with bindings in various languages?
Seriously, it's long and still common, even in the context of computing, even in programming languages. Why would you choose a long name with two words and then not choose something somewhat unique? Such a horrible decision.
Really sad given that otherwise this seems like one of the more interesting new languages I've seen on HN.
I like that the code example seems to indicate they took the concept of "ports" from flow-based programming, which might be one of it's absolute strongest points:
That is, enabling data flow connections between individual inputs/outputs, and not just between components, which otherwise is too limiting, and typically causes a lot of extra syntax to handle that routing otherwise.
Wrote about it in the context of workflow systems way back (https://livingsystems.cc/posts/workflows-dataflow-not-task-d...)
---
Edit 11:12 CET: I realize that “named ports” better captures what I had in mind here, as elaborated in a comment below.
Ports are a general feature of components in the software architecture literature (and corresponding systems).
In addition, connectors also become structured.
Objective-Smalltalk uses polymorphic connectors to adaptively and mostly automatically choose the level of granularity you want to operate at.
https://dl.acm.org/doi/10.1145/3689492.3690052
---
That aside: really cool article! Dataflow just pops up everywhere as a really, really useful abstraction, and our languages don't support it well as a general mechanism.
Instead we tend to have specialized dataflow-y tooling for one area of programming where the advantages are so significant that the impedance mismatch is worth it nonetheless.
I think you are right, and I should have done a search on that before. Found now that FBP inventor cites someone Weinberg from 1975 about them (though FBP is supposed to be from around 69-70, so might be a somewhat parallel discovery):
> Now what are "IN" and "OUT" that our pseudocode receives IPs from and sends them to? They are not the names of connections, as this would tie a component's code to one place in the network, but are things called "ports". "Portae" means "gates" in Latin, and ports (like seaports) can be thought of as specific places in a wall or boundary where things or people go in or out. Weinberg (1975) describes a port as
"... a special place on the boundary through which input and output flow... Only within the location of the port can the dangerous processes of input and output take place, and by so localizing these processes, special mechanisms may be brought to bear on the special problems of input and output."
https://www.jpaulmorrison.com/fbp/concepts_book.shtml
Still, I'm amazed at how it took so long before they became mainstream in data flow oriented libraries and DSLs.
And it seems J.P. Morrison was also highlighting Named ports as particularly useful, which is also perhaps what I should have highlighted in my initial comment above.
It's gotten better lately it seems, but a lot of tools skipped that part, which now requires tons of specialized syntax just for routing of multiple parallel streams.
---
Thank you for kind words!
The Objective-Smalltalk paper looks super interesting also, from my brief skim in Zotero! Will have to dig into it more properly next week.
it's (it is) -> its (belongs to it)
I'm not trying to be pedantic, but they're different words, and (esp. considering how capable our community is when it comes to logic and precision with programming languages) I find it strange how often this "it's / its" error is repeated. Calling it out in hopes of helping others get it right.
There's nothing strange about how often this error is repeated. It is a fault in the "design" of the English language, which violates its own rules, insofar as it has any. Apostrophes are used for both possessives and contractions, eg. "That's John's ball". Indeed possessive "it's" was historically written with the apostrophe. That the apostrophe was dropped to become possessive "its" is completely arbitrary special-case logic, and given that there is no logic behind which it was dropped from, it is easily subject to confusion because you cannot reason about which is which if you forget in the moment.
6 replies →
Yea, I think I kind of know this in theory, but tend to mix them up sometimes as a non-native English speaker. Good to try to iron out those common mistakes though for sure.
You’re wrong. It’s can mean either. Both are correct.
I’m trying to be pedantic and calling this out in the hopes of helping you get it right.
2 replies →
I don't really understand what problem this is meant to solve at first glance. It'd be nice to see a simple example program involving concurrency written in plain Python, then a discussion of the annoying bookkeeping involved in avoiding concurrency errors and what traps would be easy to fall into, and then an example of how the same thing would be implemented using Lingua Franca and an explanation of how eliminates the bookkeeping and traps.
Here are Python examples, that you can test in the playground: https://github.com/lf-lang/playground-lingua-franca/tree/mai...
Can you explain what the examples are showcasing? I looked at the Audio and Webserver examples. They give the LF syntax for doing something that is easier to do directly in Python. I'm missing the advantages of LF and why you'd want to do this in the first place.
The elevator pitch needs work.
"in any language", but then the page says "We currently support C, C++, Python, TypeScript, and Rust."
"Lingua Franca is a coordination language" but then "Not a New Programming Language".
I think I see what this is going for but the descriptions need a lot of improvement.
I think the main example on the landing page is a bit counterintuitive?
Rock Paper Scissors but the graph presents the reveal as a reaction to the observation? In a loop? And somewhere there's a min-delay of a magical 1 sec? Why 1 sec and not 0.1 sec? Can this build up and the players get out of sync? (A bit strange to 'just wait, lol' if the language aims at solving problems in distributed systems).
Overall the example would be better if it separated the game from the players and also split out the repeat loop.
Maybe let both player reveal to a host and then receive a result (and the choices) ~ This way both players can be sure that the choice of the other player is independent of the observation.
(I know that the example is 'correct' in that the choice is made independent of the observation but I think the example could be improved if it solved some of the coordination problems involved in the scenario more cleanly through code architecture).
Overall I quite like the idea of having this polyglot meta language!
> I think the main example on the landing page is a bit counterintuitive?
Still a million times better than the current Go landing page, and I am saying that as a huge fan of Go.
If you like the idea and work in robotics try out copper-rs, it works on the same underpinning concept but at compile time in rust + a graph description. The latest addition to the kernel is a profile guided scheduling feature that allows you to optimize the concurrency of the graph still at compile time based on previous timing measurements from its deterministic logs.
Erlang can do these very well. Is there anything LF better? Just asking for opinion.
The main thing this seems to provide is determinism. Where Erlang, to stick to your question, can be non-deterministic (without taking special care). I'm reading the dissertation this work is based on to see how it guarantees determinism, so at present I'm just taking their word for it.
https://www2.eecs.berkeley.edu/Pubs/TechRpts/2020/Archive/EE...
In chapter 1 they provide an example of (using Erlang syntax, completely untested so probably needs some massaging to run as I'm rusty on Erlang) this scenario, which would be deterministic in Erlang:
Because messages sent from one process to another are guaranteed to be made available in that same order, this is deterministic. They introduce a motivating example on page 5 (21 in the PDF) where a relay is introduced.
This may give the same result as the first example when run on the same node, but the guarantee is lost, it might not happen in the same order as the first version. For an example where it will likely give a different result, consider if counter were a local process to main (on the same node) while relay were a remote process (on a separate node) with high latency, it's likely that the network delay would result in {inc, 1} arriving before dbl.
The work in LF lets you write this (don't ask me how, still reading) so that the relay would be logically instantaneous even if physically it wasn't, consequently the dbl message would arrive "first" by logical time and the counter would process things as in the original Erlang code.
Of course, you can make the Erlang relay behavior deterministic, but you have to add extra code to achieve it. LF apparently gives you a simpler way to get the desired determinism without having to write the extra code yourself, it's baked into its semantics.
It appears to be deterministic in a static structure. If your program adds and deletes actors, then LF has problems. It tries to get around this with modes.
Sim-Diasca is an Erlang simulation system that implements the superdense time step mechanism used in LF via distributed time managers and a global barrier which gives repeatable results.
This project lacks a compelling sales pitch. It mentions that LF is better than actors but I also don't see no reason to believe that.
It does offer a deep dive into what reactors are but why would I bother to learn? If OP reads my comment, that's what I would add to this landing page. Show me why the alternatives mentioned are inferior.
I wonder, if there is so long research, why you have not come to conclusion that the main problem is not reactor/proactor/event loop, but writing actual asynchronous business logic. The industry has gone mostly coroutine approach, requiring special technology support and usually with lack of fine predictable execution and stack control for mission-critical cases. That's the reason why FutoIn AsyncSteps exists as concept and reference implementation in C++, Java and JS/ECMAScript. It is compatible with foreign reactors by design via AsyncTool interface.
Any language? Did not find COBOL, Fortran or C#
It's an approach to building a library. You could implement it for COBOL, Fortran, or C#.
Interesting.
Your use of the word "Reactor" at first confused me since there is a "Reactor Pattern" for event handling (https://en.wikipedia.org/wiki/Reactor_pattern) which is not what you mean.
How does your concurrency model differ from that of Erlang (the poster child for distributed concurrency)? Do you have a paper detailing your model and comparing with other languages?
I recently read Roman Obermaisser's excellent book "Event-Triggered and Time-Triggered Control Paradigms" which seems applicable to your architecture. At the bottom most level you have a global communication network based on a synchronized global clock and "Time-Triggered"(TT) semantics which is deterministic. A "Event-Triggered"(ET) communication channel is then overlaid on top of it which is non-deterministic. That way the system provides both hard real-time (i.e. TT) and soft real-time (i.e. ET) semantics.
Title is incorrect of course, it is: "Intuitive concurrent programming in a separate language than the one you use for the actual work"
... which is not to say it's irrelevant, but still: Why is it worthwhile to have a separate language for this, rather than some library with bindings in various languages?
[flagged]
[flagged]
[flagged]
Good to see flow-based programming (FBP) concepts spreading! Will add LF to the https://github.com/flux-doctrine/awesome-fbp list that I maintain
Oh god, that repo links to Grokipedia.
The award for the worst name goes to...
Seriously, it's long and still common, even in the context of computing, even in programming languages. Why would you choose a long name with two words and then not choose something somewhat unique? Such a horrible decision.
Really sad given that otherwise this seems like one of the more interesting new languages I've seen on HN.
And it doesn't give any indication of its purpose (concurrency control).