10 ms·
Elixir protocols vs. Clojure multimethods
- dnautics 5y agoYou can, you can match against the module in the struct of the second parameter, concatenate the two modules, and manually dispatch against the concatenated module. I don't really recommend this (it is not performant and feels like a code smell), but it is possible
- dnautics 5y agodefmodule A do defstruct [...] end defmodule B do defstruct [...] end defprotocol C do def foo(a, b) end defimpl C, for: Any do def foo(x1 = %m1{}, x2 = %m2{}) Module.concat(m1, m2).foo(x1, x2) end end defmodule A.A do def foo... end defmodule A.B do def foo...
- blunte 5y agoDoes performance matter considering Elixir is already very slow in per-thread performance?
- dnautics 5y agodepends on what you are doing. And it's not necessarily "very slow", moving forward as the JIT gets better and better. I highly doubt that this technique is going to be very jittable.
- brightball 5y agoHow is it slow?
- blunte 5y agoHow? Do you mean how do I know it's slow? Because it takes longer to run. Write a typical computation such as Fibonacci in Java and Erlang/Elixir and compare. Fortunately someone has already done this. Elixir is 3x slower than C and 2x slower than Java for this single thread example. https://github.com/drujensen/fib https://github.com/drujensen/fib Apparently this upsets people for me to point this out. However, I did not say that Elixir was slow in general or a bad choice. It's an excellent choice for problems which suit parallelization or which require reliable, consistent performance. Since the parent poster had commented that adding this multi-module dispatch would not be performant, I merely pointed out that the single thread peformance was already slow (as in, why worry too much about the performance cost of the multi dispatch suggestion).
- CraigJPerry 5y agoI’m starting to get a bit fed up with the down-voting behaviour here recently. It used to be that on HN you down-voted for people who were obstructing conversation, being disingenuous or in some cases being excessively disrespectful. Now having read 3 of your comments and seeing all 3 are heavily down-voted and yet the content of your messages is constructive and interesting. If you disagree with something, fine, just don’t vote on it. Save the down-votes for bad actors, not someone with a different view. The last thing HN needs is to become the kind of place where you’re actively encouraged to karma farm or whatever that term is for that behaviour on reddit.
- dnautics 5y agoI think they were downvoted because the first response was almost contentless and the other posts complain too much about the downvotes. Yes, there is some "good info" there but basically they are still presented in a relatively context-poor fashion and defensive, and willfully ignoring other points being made, and most active practitioners of elixir are aware of the context, so the comments are of questionable utility except for people who don't use the system, who may interpret it out of context and come to conclusions that are wrong. In short, they still have a shitposty feel.
- Zababa 5y agoOn the web site of things, it is faster than Rails, Django, Laravel, Express and even Spring, and this is with Plug and Ecto. https://www.techempower.com/benchmarks/ https://www.techempower.com/benchmarks/. That seems to be very good performance to me.
- blunte 5y agoPeople go nuts here on HN if they think you said something bad about their baby. I said per-thread, but I meant single-thread... as in CPU bound single process activity. That is undisputedly slow compared to languages like Java, C/C++, Go, etc. That is also very much not what Erlang is designed for. It adds a lot of overhead with the supervisor and other features which do not give a benefit for single thread CPU heavy activities. And since the parent poster mentioned the multi-dispatch approach would not be performant, I attempted to suggest that the performance cost of that would be less relevant considering Elixir is already not very performant in single thread cases. In other words, it was a moot point. I never said that Elixir/Erlang was slow for multi-thread/process distributed activities. Obviously that is where it really excels. But if you want to crunch numbers sequentially in a way that cannot be spread across multiple processes/threads, then you will find Elixir to be slow. The benchmarks you are referring to are very much multi-thread comparisons. They are specifically NOT what I was was slow.
- Zababa 5y agoYou're right about the performance of single-threaded vs multi-threaded Elixir. However, I used web apps as a comparison because they are the most common use case for Elixir. Considering here Elixir performs very well, performance could be one of the reasons why people choose it. In that case, being aware of performance pitfalls is a good thing. I don't agree that performance is a moot point if what you use is slower than some alternatives, and I think that's the main point where we disagree.
- blunte 5y agoI am not a fan of slowing something down, but in the multi-method dispatch example, unless it was being exercised in a tight loop (which would seem very much like a single thread CPU bound scenario which is already a problem), then it wouldn't be exercised often enough to make a big impact. That's just my gut feeling based on my experiences. But if this really is a big deal, then it would be fair to consider the other language features which do not contribute to the reliability, scalability, and other core Erlang/BEAM features. For example, what is the cost of pattern matching in general? Doesn't that add considerable overhead, just for the benefit of making code cleaner? If that's acceptable, then I don't see why "just one more" feature - in this case a homegrown multi-method dispatch across modules - should be considered non-performant.
- tekacs 5y ago> Now Elixir has an equivalent to multi, the Protocol. For what it's worth, Clojure also has a much closer fit to Elixir Protocols called... a Protocol. https://www.braveclojure.com/multimethods-records-protocols/#Protocols https://www.braveclojure.com/multimethods-records-protocols/... They too can only dispatch on the type of the first argument, but are more structured (you can add multiple pieces of behavior at a time) and performant than multimethods where that's the behavior you're looking for.
- tekacs 5y agoI'll also leave these here, in case the conversation inevitably turns to pattern-matched function definition in Elixir. :) https://github.com/clojure/core.match https://github.com/clojure/core.match -- pattern matching as a library https://github.com/killme2008/defun https://github.com/killme2008/defun -- using core.match to implement Elixir/Erlang-like function definition https://github.com/noprompt/meander https://github.com/noprompt/meander -- advanced pattern matching, for some fun and flavor :) What's also fun is that core.match is implemented using a paper from INRIA on how to efficiently convert patterns into decision trees: https://github.com/clojure/core.match/wiki/Understanding-the-algorithm https://github.com/clojure/core.match/wiki/Understanding-the...
- jwhitlark 5y agoI've always loved that paper. Very readable, and gives good insights.
- SatvikBeri 5y agoIf videos are more your speed, David Nolen, the primary author of that library (and article) has a talk about it as well: https://www.youtube.com/watch?v=TVJa-V6U-XI https://www.youtube.com/watch?v=TVJa-V6U-XI
- didibus 5y agoElixir's Protocols actually were inspired by Clojure Protocols. Here's Jose Valim talking about it: > I’ve learned a lot also from Clojure because, at the time I was thinking about Elixir, Clojure was already around. I like to say it’s one of the top three influences in Elixir [...] > The main, the top three influences are Erlang, Ruby, and Clojure. [...] > I was like, no, but I’m going to call them protocols because there are a lot of similarities between Clojure and Elixir in terms of them being dynamic languages and in terms of the macro system. I was like, okay, I’m going to call them protocols because the closest thing we have today to what I want is Clojure And he goes on talking about more inspiration and similarities from Clojure like Agents, etc. Full exert is here: http://blog.cognitect.com/cognicast/120 http://blog.cognitect.com/cognicast/120
- dmitriid 5y agoIt's one of those "rarely used in practice but insanely frustrating when you write a library or some generalized code". However, I'd rather Clojure got proper pattern-matching than Elixir multimethods. I find pattern matching a much more powerful, flexible and useful tool.
- Aboh33 5y agoI recently found there was a clojure implementation for .NET and also one for the BEAM Virtual Machine. Has anyone used the latter? Regards [1] https://github.com/clojure/clojure-clr https://github.com/clojure/clojure-clr [2] https://github.com/clojerl/clojerl https://github.com/clojerl/clojerl
- AkshitGarg 5y agoThere is also lfe [1] which is a lisp for the BEAM VM [1] https://lfe.io/ https://lfe.io/
- segeda 5y agoAnd also https://github.com/clojerl/clojerl https://github.com/clojerl/clojerl
- zcam 5y agoThere is also ClojureDart in the making. That one seems quite promising.
- didibus 5y agoWhy do you say "was"? They are both still actively developed even if not very popular.
- ollysb 5y agohttps://github.com/OvermindDL1/protocol_ex https://github.com/OvermindDL1/protocol_ex gives you protocols with full pattern matching.
- sandbags 5y agoBrilliant, thank you. I assumed that, with Elixir macro support, someone could implement protocols with full pattern matching. Just way above my current pay grade!
- rainygold 5y agoFeels like Elixir has stolen much of Clojure's appeal and 'thunder' as the niche pragmatic functional language.
- arvidkahl 5y agoThe ruby-like syntax and the VERY open and newbie-friendly community have definitely contributed to this. I've been to Elixir conferences, and they felt like people were just encouraging each other to build solid software WITH each other. I've not seen this level of camaraderie for other programming language communities. Elixir devs — and I am super biased here — are a special bunch :)
- rainygold 5y agoCommunity can definitely play a role though I can't help but think that Phoenix and the proselytizing done by Jose and co are the main factors. Sure, we have Luminus in the Clojureverse but its just not as easy and straightforward as the Rails-like experience of Phoenix. You don't have Hickey personally responding to comments on HN/Reddit etc.
- KingMob 5y agoHickey is extremely remote from the Clojure community. Most of Cognitect is. Really, only Alex Miller engages on a regular basis. To a lesser extent, Fogus and Ghadi do, too. The Clojurescript community is friendlier, IMO.
- rainygold 5y agoMuch to the detriment of the language imo, and he didn't help the feeling when he released 'Open Source is not about you'
- uDontKnowMe 5y agoI would agree here that the combination of being "closed to collaboration", the slow pace of development lately, and really infrequent communication from the sole owner/leader/BDFL does send a weird vibe and raises some concern regarding what direction the language is going to be going in in the future.
- kopos 5y agoHaving worked with both to create the same system (building a game server) I've found Clojure actually sits better with the functional thinking style (1 data structure, 100 functions). While Phoenix was the killer app for Elixir, and Elixir has far superior readability (using the Ruby syntax); there were couple of things that were off-putting and I struggled with them. 1. everything is inside a module was an unnecessary distraction 2. And then the separation between anonymous and named functions simply were unnecessary 3. And that I would have to declare the data / record inside a module (??) Elixir felt like a functional language un-necessarily trying to look like a class based language. I sometimes feel that had Elixir had only supported functions outside of modules... oh that freedom. But some of the thought that went into Flow, Channels (which has become the de riguere now), mix (developer ergonomics ftw), those micro-second latency responses, distillery are still too classy and amazing.
- jeremyjh 5y ago> Elixir felt like a functional language un-necessarily trying to look like a class based language. Not really. Named functions live in modules because that is how it is done in Erlang; Elixir is compiled to Erlang's abstract syntax. In practice does anyone define Clojure functions outside of a namespace? Haskell functions are always defined in modules too, do you think they got that from class based languages?
- divs1210 5y agoThe problem here is that its inconvinient to define a function at the Elixir REPL because it demands that it be put inside a module. Clojure REPLS allow switching the namespace, and anything you define goes intoo the current namespace. So it is more ergonomic.
- tomjakubowski 5y agoIEx will let you define a module at the REPL. Combine that with a macro (exercise for reader) in your .iex.exs which expands a function into a module definition and imports it and you're in business. iex(1)> defmodule Foo, do: def bar(x), do: x + 1 {:module, Foo, <<70, 79, 82, 49, 0, 0, 4, 192, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 135, 0, 0, 0, 15, 10, 69, 108, 105, 120, 105, 114, 46, 70, 111, 111, 8, 95, 95, 105, 110, 102, 111, 95, 95, 10, 97, 116, ...>>, {:bar, 1}} iex(2)> Foo.bar(1) 2 iex(3)> import Foo Foo iex(4)> bar(1) 2
- tobyhinloopen 5y agoUsing dashes in function names? Blasphemy
- nsonha 5y agoprotocols are still just single dispatch like interfaces and virtuals in other languages. This person uses a title that makes it seem like Elixir has multiple dispatch, only to conclude at the end that protocols are nothing like multimethods.