4 ms·
"Is this because the erlang/otp concepts are insufficient or outdated?" Insufficient or outdated is a pretty loaded term. What they are is really, really tied
by jerf 4y ago
"Is this because the erlang/otp concepts are insufficient or outdated?"
Insufficient or outdated is a pretty loaded term.
What they are is really, really tied to the Erlang worldview, of immutable functions, mailbox APIs that can receive messages out of order, the way they have "behaviors" as a really limited kind of class system, and other details of Erlang. This isn't a criticism, it's really a good thing. An Erlang library should harmonize with Erlang, after all.
But when you port them into environments that don't have all those characteristics, the optimal library that harmonizes with that environment looks different. In Go, for instance, rather than the whole gen_server thing, the idiomatic approach to this sort of thing tends to look a lot more like:
for {
select {
case msg1 := me.Chan1:
me.handleMsg1(msg1)
case msg2 := me.Chan2:
me.handleMsg2(msg2)
// etc.
}
}
Trying to jam Go code into the gen_server framework is very klunky.
Another reason is that while Go and Erlang both have fairly weak type systems, they are weak in very different ways. It is idiomatic in Erlang to label what kind of message something is by making it the first atom in a tuple. Then you can use Erlang's pattern matching in functions to implement many different message types based on what you send to the gen_server. This ports into Go terribly. Go does it in very different ways.
"I suggested it would be good to capture these core concepts in standardized libraries for a range of languages, but now I am not so sure."
No, it really doesn't work. Even two languages in the same basic family can end up with significant differences in patterns (witness Ruby versus Python, for instance, virtually the same language, significant difference in what is idiomatic). Trying to stretch a library from a language that is based on a super weak type system (on purpose; it is part of the Erlang solution to cross-version communication), immutability, pattern matching, and mailboxes into a language with a weak type system in a different way, mutability, conventional function calls, channels (very different than mailboxes), and all the other relevant differences may be theoretically possible, but it will always result in foreign environments in the language.
You can actually see this in the real world by the way that C is the de facto cross-language in-process bus on Linux. It bends everything that has to use it. Personally I consider it one of the biggest impediments to a new language getting off the ground because of the design decisions it forces on a new language at a young age. We are, slowly, getting past this in a variety of ways, but it's hard.
- pdimitar 4y agoCan you elaborate on how are Erlang process mailboxes different than channels, please? I view them as hear-identical but I haven't thought deeply about it.
- klabb3 4y agoMe too! I don’t know Erlang enough, but Golang channels accept anything, including mutable data, file descriptors etc. If you want to send to different machines you need glue and refactoring in order to get some similar behavior, since channels are in-process only. My understanding is that Erlang require messages to be self-contained/immutable (even serializable?) which would make it possible to simply move an actor (process) to a different machine, or even multiple machines? If you know Erlang, please fact check!
- weatherlight 4y agoMessages between Erlang processes are simply valid Erlang terms. That is, they can be lists, tuples, integers, atoms, other pids (process identifiiers), strings, and so on. However, Erlang and Elixir's AST is also composed of valid Erlang terms, so as I understand. you can send entire Erlang/Elixir programs as messages. To answer your question, Yes, it is possible, but there is no "Move process to node" call. However, if the process is built with a feature for migration, you can certainly do it by sending the function of the process and its state to another node and arrange for a spawn there. To get the identity of the process right, you will need to use either the global process registry or gproc, as the process will change pid. There are other considerations as well: The process might be using an ETS table whose data are not present on the other node, or it may have stored stuff in the process dictionary (state from the random module comes to mind)
- throwawaymaths 4y agoFor starters, it's easy to receive messages across a cluster, and if you send a message across the cluster, and it contains a process id, that process id is magically converted to it's node local value on receipt.
- 4y ago