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

Elixir is kinda nice. I like their macros, db querying layer and mix and low latency.

But I feel no typesystem would bite me in bigger project.




The type system problem is somewhat mitigated by ubiquitous use of pattern matching. In python, the function

  def foo(mymap):
     blah
Has no real information about what my map is. In contrast, a staticly typed language like Java would have

  public static HashMap<String,Integer> foo(HashMap<String,Integer> mymap){
    return mymap
  }
which encourages you to have a lot of classes defining different types of things, which is rigid, but at least makes it clear what exactly the function is expecting. Elixir is somewhere in between, where you'd write

  def foo(%{"username" => username, "password" => password}) do
     {username,password}
  end
which makes it abundantly clear what the function expects ( a map, with keys "username" and "password"), and handily unpacks those values for you, making it feel more immediately useful than "In the future it'll be nice to have more clear code", which helps with adoption.


In practice, the Python example is likely to have considerable information hidden in the “blah” from which existing tooling can often infer much of what would be declared in a language with mandatory explicit static typing; and it has existing tooling for optional explicit static typing, too.


So does Elixir with typespecs and Dialyzer, but I'm talking about quick, at a glance analysis of a function definition. Which is really the only benefit from a brittle type system like C or Java's, in contrast to a proper type system like Rust's or Haskell's, which have their place and cannot be adequately replaced merely with pattern matching.


Python 3.10 introduces pattern matching: I've not had the chance to really play with it yet so can't say how fully featured it is, but you can do something like:

    def foo(login_data):
       match login_data:
          case {"username": "foo", "password": "blah"}:
              return True
          case _:
              return False
In addition you can use type hinting:

    def foo(login_data: dict[str, str]) -> bool:
        match login_data:
          case {"username": "foo", "password": "blah"}:
              return True
          case _:
              return False
Unfortunately I don't think you can yet do the neat argument unpacking as per your Elixir example, but it's some of the way there.


I don't know that that's the big issue with dyanmicism, at least not for me. In Ruby the main thing that bugs me once in a few months is a silly typo - calling a misspelled ivar or method. It happens maybe once in half a year but it's still humbling when it happens. It's rare because usually your IDE is very good in spotting these mistakes - even in Ruby, and also decently tested code should break right away. But I do wish and hope the tools will become better - whether it's Rubocop or something completely new, that the chance of this happening will be almost zero. It's not there.


I worried about this too, but I found that 90% of the places I want "types" are elegantly handled with pattern matching and what other langs would call "function overloading." I also love that you can treat structs like a map, which I feel is the best feature from javascript.


I feel there's more to the dynamic language world that's not clearly explained by the lack of types. I have used both Python and Elixir for production apps, and I get an order of magnitude more type errors with Python than Elixir, for some reason.

IMO it's a disservice to compare Elixir's typing to languages like Python, and we need a new category to distinguish the two.


The fact that there are a lot of standard behaviours (GenServer, Supervisor, Agent, e.t.c) and conventions followed makes this not such a big issue for me. Dialyzer is also a great tool which catches a lot of errors for me.




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

Search: