3 ms·
It looks like a nice language with the {} syntax to tease all the C and Java developers out there. That's more important than it looks to help spreading the lan
by pmontra 2y ago
It looks like a nice language with the {} syntax to tease all the C and Java developers out there. That's more important than it looks to help spreading the language.
The OTP example lets me state one of my few sore points about all the BEAM languages I worked with or looked at: the handle_this / handle_that madness. Search for "type AsyncTaskMessage" in the post to get there.
I don't want to write code like this (I omit the details, ... are ellipsis from mine)
type AsyncTaskMessage {
Increment(reply_to: Subject(Int))
Decrement(reply_to: Subject(Int))
}
fn handle_async_task(message ...) {
case message {
Increment(client) -> {
code ...
}
Decrement(client) -> {
code ...
}
...
}
I want to write code like this
type AsyncTaskMessage {
Increment(reply_to: Subject(Int))
Decrement(reply_to: Subject(Int))
}
fn Increment(client) {
code ...
}
fn Decrement(client) {
code ...
}
or any variation of that, maybe this OO-ish one (after all this is a stateful object)
type AsyncTaskMessage {
fn Increment(reply_to: Subject(Int)) {
code ...
}
fn Decrement(reply_to: Subject(Int)) {
code ...
}
}
Maybe one of the next BEAM languages will handle that automatically for us.
- cess11 2y agoNot sure what the macro story is in Gleam but in Elixir you could write Increment/Decrement macros that ties into the process API. Kinda contrived example though.
- lpil 2y ago> Maybe one of the next BEAM languages will handle that automatically for us. It not being automatic is a feature as that pattern is only what you want in the trivial case, but in real programs you are going to want more control. In early Elixir there was a relatively popular macro library[1] that offered what you ask for (see code example below) but as Elixir matured and started being used in more than toy projects it was largely abandoned. defmodule Calculator do use ExActor.GenServer defstart start_link, do: initial_state(0) defcast inc(x), state: state, do: new_state(state + x) defcast dec(x), state: state, do: new_state(state - x) defcall get, state: state, do: reply(state) defcast stop, do: stop_server(:normal) end [1]: https://github.com/sasa1977/exactor https://github.com/sasa1977/exactor
- pmontra 2y agoGreat. That was basically all we used of GenServers in the Elixir projects I worked on. I remember one or two handle_info but nearly all our GenServers were (in OO parlance) objects with methods to update their status, trigger actions and sometimes read the status.
- hjadal 2y agoCould you possibly do this by transpiling to Gleam? Seems like the transformation is possibly simple enough that it could be done without implementing a new language.
- simoncion 2y agoYeah, this syntax kinda sucks fn handle_async_task(message ...) { case message { Increment(client) -> { In Erlang to "just call the damn function" I'd write it something like handle_cast(R=#message{type=increment}, S) -> work_module:increment(R, S); handle_cast(R=#message{type=decrement}, S) -> work_module:decrement(R, S). Or I'd use maps instead of records.