Hacker News new | past | comments | ask | show | jobs | submit login

Yeah, elixir provides Registry which is what I use for simple state management or directly use ets.

See below (jswny) for more clarification.




Unfortunately had a bug I found today in which an event_notifier genserver was calling a method that checked against the database for the the state of an Event, to decide whether to send a notification and then update the event to record that notifications were sent and upon successful update send the notifications. But in the query to construct the list of users that should be notified, the User module was not imported at the top of the file and the notifications were failing to send. Of course, if the path had ever been run, it would have obviously failed and been the simplest type of error to rectify. This is why it's generally not an issue and is actually nice as it gives you direct visibility into dependencies. But, on rare exception, when you don't test the path because it's dependent on time-dependent state and are overly confident in the suitability of the untested code you're deploying to production, you get bit by the compiler that quietly warns and lack of static analysis (oh nice writing this comment just made me discover https://github.com/rrrene/credo)


You might also be interested in https://github.com/jeremyjh/dialyxir

I use both dialyxir and Credo in my projects


You can run the compiler with --warnings-as-errors


Can you explain what you mean about module naming? I’ve done a good amount of Elixir, and I’m puzzled because I don’t know what you are referring to at all.

Most libraries and frameworks I’ve used enforce things on your modules via behaviors which have nothing to do with naming. Perhaps you are talking about naming functions for behaviors? Because I think it’s the same in most languages that “overridden” or “implementations” of functions for modules/classes that use some kind of interface must be named the same as the interface definition.


> Perhaps you are talking about naming functions for behaviors? Because I think it’s the same in most languages that “overridden” or “implementations” of functions for modules/classes that use some kind of interface must be named the same as the interface definition.

Yes. In typescript, you can have abstract classes or interfaces to implement which gives you more information (intellisense, visible errors, type information) and make the contract more explicit. I was trying out phoenix and I didn't get any hints about the methods to implement in the module. I was relying on documentation for that. If there was a way to say use @some_spec and get information about it in the editor. It would have helped out.


The compiler will warn you about things like unimplemented functions that are required by behaviors, and there are plugins for various editors to display errors/warnings inline.

There's also Dialyzer (and various IDE integrations) for some level of static type-checking.


there are language features directly for this. no need to rely on compiler hints or dialyzer.

elixir people really should learn erlang.

if you ever saw a coffeescript person struggling to do things that are straightforward in js, because they didn't bother to learn js? that's what you're doing now


This is the main reason why I learn programming languages to broaden my knowledge, but when it comes to production code, only platform languages matter.


Well no, it's just that Elixir is built on Erlang, so everything Erlang has is in Elixir

If you learn the base language, you get more powerful in the descendant language as well


If one only uses the base language, no need to worry about the fate of the descendant language or how it exposes base language features.


This means you're arguing that one should never learn anything except machine code because machine code is what it all turns into at the end of the day.

Only you DO use languages that end up as machine code, and the idea of understanding machine code to better utilize something like C isn't outlandish.


Nope, use C/C++/Perl/awk with UNIX, Java with the JVM, C++/Swift/Objective-C with iOS/macOS, Java/Kotlin/C++ with Android, VB.NET/C#/F#/C++ with Windows, JavaScript/WebAssembly with the Browser,.... and naturally Erlang/C with BEAM.

No need for extra build tools, FFI with the platform language, additional debugging tools, the urge to create wrapper libraries that feel more idiomatic into the guest language, waiting for the guest language to come up with ways to expose new platform capabilities,...

Guest languages are good for experimenting new ideas that eventually get adopted by the platform and then the world moves on, and they turn into the next CoffeeScript.


> In typescript, you can have abstract classes or interfaces to implement

In erlang these are called "behaviours"

.

> I was relying on documentation for that

Consider reading the Erlang documentation. The Elixir people really don't understand Erlang very well, and are trying to manufacture Ruby on top of a language that already gives them solutions to their problems that they just can't see.

.

> If there was a way to say use @some_spec and get information about it in the editor. It would have helped out.

Basically every IDE that speaks Erlang knows behaviors. They're as fundamental to the language as header files are to C/C++.

Elixir tried to "do away with them" because Elixir thinks they're "confusing" but they're actually really important tools.


> Elixir tried to "do away with them" because Elixir thinks they're "confusing" but they're actually really important tools.

That's completely inaccurate. They are an important part of Elixir and they are fully documented.

Elixir even has annotations that allow you to say "this function maps to a behaviour's callback". For example:

    @behaviour GenServer

    @impl true
    def handle_info(msg, state)
Those are important because, with optional callbacks, you can make a typo on the function name or on the number of arguments and you won't get any warning, in both Erlang and Elixir. "@impl true" allows you to close this gap.

So we do support behaviours and we have added more static guarantees compared to what you would find in Erlang.

> The Elixir people really don't understand Erlang very well

It is a bit depressing it has come to this but my long list of contributions to Erlang/OTP through pull requests, discussions, EEPs, etc say otherwise.


I wouldn't feed the troll. The many people who know and appreciate your language realise how much of an improvement Elixir represents over Erlang.

Including Joe Armstrong himself... https://joearms.github.io/published/2013-05-31-a-week-with-e... ^_^


Elixir hasn’t done away with behaviours. They exist in the language and are used to implement features in the standard library itself and many libraries in the ecosystem.

You don’t have to go to Erlang documentation to learn about them since they are documented in Elixir as well [1] [2].

[1] https://elixir-lang.org/getting-started/typespecs-and-behavi... [2] https://elixir-lang.org/getting-started/typespecs-and-behavi...


Elixir does not try to do away with them. They are covered in the official guide: https://elixir-lang.org/getting-started/typespecs-and-behavi...

As soon as I add @behaviour to a module, I get IDE autocomplete and compiler warnings if a function has not been implemented.

I do agree that I have not seen a lot of behaviour use in the wild, even in cases where it's clear that they would be beneficial. Elixir developers seem to have some blindspots.


> As soon as I add @behaviour to a module, I get IDE autocomplete and compiler warnings if a function has not been implemented.

It is exactly what I was looking for. Thanks for mentioning it.


If you learned Erlang, you'd realize these were both terrible choices, and that you ought to be in the process dictionary


Can you explain more?

I am looking at the answers from this stackoverflow question: https://stackoverflow.com/questions/1483550/in-erlang-what-a... and the Erlang docs.

I don't get the impression that they are comparable.


They are not. There is a reason why seasoned Erlangers all tell you to avoid the process dictionary. Erlang docs[0] say the following:

> Note that using the Process Dictionary:

> - Destroys referencial transparency

> - Makes debugging difficult

> - Survives Catch/Throw

> So:

> - Use with care

> - Do not over use - try the clean version first

[0] https://www.erlang.org/course/advanced#dict


[flagged]


> Hi, I'm a seasoned erlanger, and we do not all tell you that.

Seasoned Erlang developer here too (10+ years).

First of all, the original post wanted to share data across requests. Given each request is typically handled in separate process, you simply cannot use the process dictionary to share this data. So your original comment completely missed the mark.

Second of all, I would say most of the Erlang community actually agrees with the Erlang official documentation linked above. For example, for a long time, Cowboy had this in its README:

> No parameterized module. No process dictionary. Clean Erlang code.

And the reason is simple: the process dictionary is about state within a single process. This data cannot be easily shared (you can with erlang:process_info/2 but that adds a process lock). Therefore, most times people resort to the process dictionary is to pass data within a process, implicitly, and passing it functionally (the clean way) is often better. Using ets for the same purpose would also be frowned upon. The process dictionary should only be used almost exclusively for metadata.

You probably won't be inclined to take my word for this, so here is a proposal: send a pull request to remove or update the linked notes above from Erlang/OTP docs and see how well it will be received.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: