Ed W
--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-talk+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/552BE7A7.6060505%40wildgooses.com.
For more options, visit https://groups.google.com/d/optout.
However I think you are missing the point of behaviours. Behaviours are extremely useful. For example, a GenServer defines a behaviour. A behaviour is a way to say: give me a module as argument and I will invoke the following callbacks on it, which these argument and so on. A more complex example for behaviours besides a GenServer are the Ecto adapters.
However, this does not work if you have a data structure and you want to dispatch based on the data structure. Hence protocols.
> Q: Why isn't more of Elixir implemented in protocols?
Because we have not identified more protocols. One could say: we could make +, - and so on all based on protocols however I don't think protocols should be the default. They should be opt-in both when defining and when invoking because I prefer my code to be assertive than generic. I wrote a little bit about it here: http://blog.plataformatec.com.br/2014/09/writing-assertive-code-with-elixir/
> Q: Why aren't Set and Dict implemented using protocols. Is it because of performance issues in development mode? Does the performance of Protocols become equal to the current implementation in release mode after consolidation?
Partially yes and yes, respectively.
For the first question, besides the performance concern, I think large protocols are a smell and you can't efficiently implement a dictionary with a small set of functions. So in order to not open up a precedent for large protocols in Elixir and solve the performance issues, we have decided with the current implementation.
> However, right now there is probably a bunch of code written using "HashDict.xxx" and to use my new datatype I guess I would need to implement a new implementation CleverNewDict, and then update any HashDict references (or hopefully the user used Dict.xxx instead?). This feels like it would hinder implementation of drop in replacements for Dict right now? Do we care?
Not sure I follow. Can't you use the Dict module if you want it to be generic?
Pointy end of the question:
I implemented a Priority Queue in Elixir as a learning exercise:
https://github.com/ewildgoose/elixir_priority_queue
The Priority Queue implementation requires a Heap datatype to operate. I would like to standardise that Heap datatype so that I can experiment with performance using different underlying Heap implementations. I seem to have two ways I might proceed:
- Using a Protocol for my Heap. I would define my required implementation and then very flexibly I could drop in any old module which behaves something like a Heap. eg It might make sense to use something wrapping Redis for certain use distributed cases, it might be be better to use a native datastructure for others. In no case will the PQ algorithm need to know. Also any user can implement the protocol between PQ and some potential datastructure, without needing to open the implementation of either.
- Use Dict/Set as an implementation guideline. This involves writing a behaviour for the Heap interface, and offering polymorphic dispatch by implementing dispatch through implementation of a "target()" macro in the Heap module. I found this quite tricky to understand when first reading the code and it seems to hinder implementing new Heap types (requires the implementer to comply with *my* polymorphism implementation and the new candidate module must be opened and modified to work in a certain way, ie we require access to the candidate module code (or wrap it))
Given I specify that performance is vital, does this mean I should choose the Dict/Set type (hand rolled) polymorphism? Is the more general answer: "Use Protocols whenever you can, but if performance is vital then use a handrolled polymorphism based on the Dict/Set style implementation"?
I see your comment as correct in as much as we *could* dispatch based on data structures *if* everyone who wrote a datastructure agreed on a common contract for the function names and meaning and implemented their datastructures with those contracts in mind (ie this is just what we do with a "behaviour") - clearly this rarely happens, hence the need for protocols?
But for practical purposes I don't see that a behaviour is any different to a protocol, other than a behaviour *forces* the glue logic into the datastructure module, rather than allowing it to live outside that module, as with a protocol?
I guess I don't understand what problem you perceive in allowing polymorphism to permeate easily in order to disagree?
(Remember many new users will come from Ruby where the expectation is quite the opposite and "quacks-like-a" is quite the norm?)
To my eye this is just crying out to be a Protocol? I can then trivially turn any datastructure into a "Dict" and of course I get to keep all the pieces and the responsibility for ensuring this works out...
--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/552CE675.40205%40wildgooses.com.
But for practical purposes I don't see that a behaviour is any different to a protocol, other than a behaviour *forces* the glue logic into the datastructure module, rather than allowing it to live outside that module, as with a protocol?
Can I ask you to comment on this below then? I think what you are confirming is that *your* opinion would be I should use the behaviour based "polymorphism-alike" that is used in the Dict/Set implementations in Elixir core?
I guess I don't understand what problem you perceive in allowing polymorphism to permeate easily in order to disagree?
Because with protocols my code becomes less assertive and therefore harder to understand. When I see to_string(data), I have no idea what data is. Up to that point, my brain keeps a blank space with the information that is must implement String.Chars. However, if I see Atom.to_string/1, I know exactly what it should be.
So I optimize first for readability and understanding of the code. Polymorphism is very handy but it should be opt-in.
If we defined a Dict protocol, we had three options:
1. it would be too large in order to implement all functions efficiently2. it would be too tiny, with just some functions, and therefore incomplete and less useful3. it would be too tiny, with a set of primitives, which would make assumptions on all other Dict implementations possibly make all other operations slow. Yes, you can implement Dict.update as a get and put, but that requires accessing it twice. You would have trade-offs like these every other function.
That's why a protocol doesn't make sense. You would put yourself in any way into a corner.
Robert -
As cited in this thread, Dicts and Sets are simple data structures in Elixir that are implemented via a Behavior. The methods in those functions derive the module from the data structure passed in and dispatch accordingly. See https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/dict.ex
Let's move the discussion around Dict and Set to a separate thread specifically around those code changea. Regarding a minimal protocol and a full protocol, we already have a precedent with Enumerable.count/1 where there's a default implementation.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/ebab9b53-b169-4c06-9017-a89f1a315dea%40googlegroups.com.
Understood. I didn't intend to come across that way, I was just trying to use a specific example to try and draw you out on your opinion on when a new coder should learn to use behaviour vs protocol