Logger would be thin wrapper over logger and would support structured logging (I know why this isn’t a fact, I just would like it to happen in future). Also it should support more logging levels (all syslog levels).
Shorten Kernel.SpecialForms (ex. remove with from there)
Maybe merge with and for to provide “do-like notation” where I can match and iterate over data in one block
Change meaning of def and defp or reintroduce export list
Probably remove nil special atom and instead always require it to be declared, especially as Erlang do not use nil that often
To encourage people to create as functions private whenever possible. The smaller public interface the better IMHO (also this is better for compiler as it can optimise out private functions (for example inline them) while it cannot do the same for public functions.
some_value |> (& &1/10).()
But that is incredibly ugly, You can write it also as:
Another thing I would really love is decent support for testing (spies and stubs and fakes) and support for testing concurrency (no decent tools for that really).
Truly the thing I fight the most with Elixir is the lack of support for testing …
Between ExUnit, Behaviours, Protocols, Mox, and passing functions around I’d say we have more than enough dependency direction control for whatever testing/mocking one might need. If anything the problem might be that there are a lot of different ways to manage dependency direction and when to use what flavor of Behaviours, Protocols, and configuration is less clear.
Mocks and Explicit Contracts is the article shared most on the subject which mostly discusses using Behaviours for tests and mocks. This article shows a few more techniques. When do we use Protocols over Behaviours or over passing a function around? What questions do we ask about our scenario to determine which technique is optimal?
Just pass module name as an argument to the function with the name of the module or use other form of remote call to the provided module (application configuration, any of the N mocking libraries out there).
What you mean by testing concurrency? You mean to check if there are no interleaves then there is Concuerror, however it has no good wrapper library for Elixir yet (I am working on it). But honestly, what is missing in concurrency testing though?
Why pass an entire forest if all I need is a banana?
Not only that, I am yet to find a single testing library that allows me to do half of what sinon js does. Simple things like “Stub A returns different results depending on how many times it is called” are nowhere to be seen. So no, the way I see it, the current set of tools is insufficient at best.
Ah yes, Concuerror … The problem with testing concurrency and inter-processes communication is that Elixir (and Erlang for that matter) have little support for it. This is a topic widely discussed and even acknowledged by Jose Valim (irrc). Furthermore, if memory serves me right, Joe Armstrong is working on tools to make concurrent processes testing and development better (his focus on protocols) and this is the main reason why the Actor model is not as widely spread across Elixir, with most people only using processes for runtime benefits instead of using them to manage state (like a real Actor model dictates).
Concuerror is a step in the right direction, don’t take me wrong, but when it comes to debugging and tool support, the the major brains agree there is a lot to be done. I am not a major brain in anything, but I recon their knowledge is far deeper than mine and so I choose to not disagree
Because for that you need store state somewhere. JS has mutable data, Elixir/Erlang doesn’t. You can use example I have provided you in the other topic with counters, or you can use Agent for storing that data, or any other form that you find suitable for your case. Not having all “magic” built in (especially in standard library) is good thing, because often it is much easier to update external dependency rather than updating language core. And reason why such feature is not seen often in Elixir is that everybody should prefer pure functions over impure, and what you describe there is highly impure function.
I agree as well, but TBH could you give us an example of good, existing, solution? The reason why this is hard and lacking is because it is terra incognita in general, not in BEAM universe only. There are tools like TLA+, but these aren’t broadly used.
I plan to further delve into this in a separate discussion. Your insight will be most welcome.
For me (and I will apologize you if you outright decide to murder me for what I am about to say) a semi-decent example of a tool is how Eclipse was integrated with Java for testing threads. It would allow you to debug several threads using the debugger and using break points, something I dearly miss with Elixir VScode plugins (maybe you use a better IDE?).
It was not without it’s issues however, not even sure if it is being maintained now with all the Java (Jakartat?) de buckle.
The problem there is the design of the language and their concurrency primitives. In Java the process is ran from top to bottom, and while it has some communication primitives, it is mostly linear. On the other hand Erlang is build on top of processes and messages, so this is the problem. “Porting” ideas from imperative language like Java to concurrent language like Erlang do not work well in some cases.