What does your ideal version of Elixir look like?

community

#1

One thing I love about our community is the high standard set by the Elixir, Phoenix, Nerves and Erlang core teams… another thing I like is how others wish to raise those standards even higher :lol:

So I thought it would be a nice idea to post a series of threads for just that :003:

Please let us know what your ideal version of Elixir looks like in this thread :smiley:


Other threads in this series


What do your ideal versions of Erlang/OTP/BEAM look like?
What does your ideal version of Phoenix look like?
What does your ideal version of Nerves look like?
#2

My ideal version of Elixir would be Elixir but without all the issues I mentioned in my first impressions post:

And monads. It would have monads as first class citizens :stuck_out_tongue:


#3

What would first class monad support look like?

A monad protocol can be implemented today for your data structures, and I believe there are several libraries such as witchcraft that will supply one for you.

We have some monad do syntax like behaviour thanks to the with syntax too, though it’s not something you can extend.


#4

My ideal version of elixir would be one where I could do something like this.

some_value |> /10 

I know it’s a dumb use case and probably pointless to implement, but it’s the only thing that ever really annoys me when coding.


#5
  • 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

#6

Something among the lines of Haskel with the difference that I actually want Elixir to have success :stuck_out_tongue:

When I first checked witchcraft it was less documented. It has evolved quite a bit since then, looks like I will give it another look.


#7
iex(1)> some_value = 420
420
iex(2)> some_value |> Kernel./(10)
42.0

#8

Or

some_value |> &(&1/10)

Edit: Scratch that actually, It’s probably wrong. I’ll test and fix this latter.


#9

I really like these suggestions!

Could you explain what you would like to be different about defp?


#10

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:

some_value |> Kernel./(10)

However this one cannot be rewritten at all:

some_value |> (& 10/&1).()

#11

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 …

As a good example, have a look at sinon.js APIs…


#12

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?


#13

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?


#14

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 :stuck_out_tongue:


#15

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.


#16

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.


#17

Can probably guess what I’ll say, but first and foremost a good strong static typing system, that would save me well over 90% of my standard bugs. ^.^;


#18

Have you considered alpaca?

Also, a post that may interest you :smiley:


#19

Believe me, he did. As far as I know, he even contributed to it.


#20

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.