If you could change one thing in Elixir language, what you would change?

Ok, so it make sense.
Thank u for answer

Iā€™ll check it out, thanks!

This might go against the grain, but Iā€™d love some OOP. I suppose in Elixir this is done through ā€œprocessesā€. Still trying to wrap my head around functional. Iā€™ve found a hybrid approach provides much more flexibility.

Should I be looking at processes for this? Iā€™ve been able to simplify a great deal through functional approaches.

That plus static typing (though we are 25% of the way there through dialyzer). Sadly, doesnā€™t look like either will make an appearance due to nature of underlying architecture.

https://www.theerlangelist.com/article/spawn_or_not

This is a good read to help wrap your head around the concepts of modeling with processes.

5 Likes

Appreciate it!

It might be valuable to discover what elements you feel you are missing out on - for example:

  • mutable vs immutable
  • shared vs not shared
  • designing flow of control vs flow of data (values)
  • etc.

There are already some topics around that explore the differences and nuances. Like:

2 Likes
  1. improve the REPL with a few things:

It would be nice for history to persist between invocations.
It would be nice for multiline invocations to be up-arrowable (if youā€™re curious to how amazing this is, try julialang).
It would be nice to be able to define functions in the REPL scope without having to define a module (I know, this is nigh impossible).

  1. etc:

Can I make a module compile-time only? We can currently do this with packages using runtime: false, but not on a module-by-module basis.

3 Likes

You might add to your .bash_profileā€¦

export ERL_AFLAGS="-kernel shell_history enabled"
8 Likes

What you mean by that? What would you expect out of such module? You can define module that will contain only macros, so effectively it will end mostly empty in production, mix help compile.app mention option :modules but I do not know if this is respected anyway by the compiler it is.

This is actually not impossible, it just depends on what the shell interpreter decides to do. For example the Erlang shell has a simple way that if you have a module :user_defaults then you can call these functions without a module prefix. Yes, I know, a module but it is on the way. The LFE repl allows you the define both local functions and macros without a module.

4 Likes

Sometimes itā€™s useful for macros to call functions which are then unit tested.

:modules option seems like itā€™s what i want, but itā€™s somewhat poorly documented:

.app files also expect other options like :modules
and :vsn

is all it says. Is there another place where I can find what it does or should I just chase the code?

The :modules option wonā€™t make modules disappear or make them compile-time only. It exists only for catalog purposes and to check for module conflicts when building a release, it doesnā€™t affect runtime. So AFAIK there is no reason to change it and it is better to let Mix fill it in. :slight_smile:

2 Likes

If you want to have test-only modules then add new path to the :elixirc_paths (commonly used path is test/support) and define such modules there, or if this is for testing then you can define such module within your test module, ex.:

defmodule MyTest do
  use ExUnit.Case

  defmodule Foo do
    use MyMod
  end

  test "Foo module has function foo/0" do
    assert function_exported?(Foo, :foo, 0)
  end
end
1 Like

no, that doesnā€™t help. Hereā€™s what Iā€™m doing:

defmodule MyMacros do
   defmacro mymacro(foo) do
      ast_transform(foo)
      foo
   end
   def ast_transform(foo) do
      <calls other functions>
   end
end

I donā€™t need ast_transform (and friends) at runtime. Itā€™s compile-time only. I might want to unit test ast-transform, because itā€™s rather complicated.

1 Like

When I first started learning elixir it felt inconvinient not to have a ternary operator
foo = bar ? buz : buzzz
and to type

foo = if bar do
  buz
else
  buzzz
end

instead. I got accustomed to it as well as to calling captured functions with a period sign between function variable name and arguments butā€¦

recently started learning Dart (thanks to Flutter) and found there besides of ternary operator such goodies:
var foo ??= 'bar';
which means "if foo is not null then do nothing, else set it to ā€˜barā€™ "
var foo = bar?? : buz;
which means ā€œset foo to bar if itā€™s not null else set it to buzā€
var foo = bar?.buz;
which means ā€œif bar is not null then foo is equal to buz property of barā€

I think this brevity adds to Dartā€™s expressiveness. I know that question mark and colon are really busy in Elixir, Iā€™m just missing for some consice substitution for ternary operator.

Iā€™m not a fan of those operators in dart, and if they are idiomatic, maybe its even a reason to not start with it?

I like the expliciteness of foo = if foo == nil, do: 'bar', else: foo. Even my son might grok whats going on here (after he had the first couple of english lessons). He probably wont understand var foo ??= 'bar'; without having explicitely learned dartā€¦

4 Likes

Oh, and break operator for breaking loops. Last time I had to do it like in here: https://gist.github.com/lerencao/bd6f3ddf3fb468a7e52ae31f2f07f995
I just remember my surprise not to have it in Elixir from the boxā€¦

Enum.reduce_while? Explicit recursion?

Stop yelling the l world and start using recursion and higher order functions!

4 Likes

Huh? You can break from a loop just fine:

iex(1)> defmodule Blah do
...(1)>   def bloop(i) do
...(1)>     if i < 10 do
...(1)>       0
...(1)>     else
...(1)>       i + bloop(i-1)
...(1)>     end
...(1)>   end
...(1)> end
{:module, Blah,
 <<70, 79, 82, 49, 0, 0, 4, 224, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 128,
   0, 0, 0, 15, 11, 69, 108, 105, 120, 105, 114, 46, 66, 108, 97, 104, 8, 95,
   95, 105, 110, 102, 111, 95, 95, 7, 99, ...>>, {:bloop, 1}}
iex(2)> Blah.bloop(15)
75

Remember, in a pure functional world loops are just recursive calls, to ā€˜breakā€™ out you just return instead of continuing the recursion. :slight_smile:

Hmm, so:

foo = foo || "bar"
foo = foo && bar || buz
foo = bar && bar.buz

Though you didnā€™t say what the last one does when bar is null, guessing it sets foo to null since expressions have to return something, so I did the same.

That dart syntax Iā€™m not a fan of, thatā€™s getting into operator overload thereā€¦ >.>

5 Likes