KallDrexx

KallDrexx

Practical difference between protocols and function pattern matching?

In my current project (first elixir project) I have different messages each represented by its own struct which defines the unique view of that message.

I then created a module to act as a handler for those messages, so I can call MyModule.handle(message, state). The actual implementation for the handle function uses pattern matching in the function definition so each function only handles the message type it knows (e.g. def handle(message = %MessageType1{}, state), do: ...).

It then occurred to me that this is the same functionality offered by protocols, and got me wondering if I should be using protocols for this scenario rather than function pattern matching.

The only advantages I could see with protocols is that external systems using a library that defines a protocol can extend it out to their own custom structs. On the other hand, function pattern matching allows you to code fall-through cases.

Are there any other practical reasons why I should choose one or the other?

Most Liked

bbense

bbense

As a rough rule of thumb, pattern matching in function heads is going to be faster than Protocols.

Protocols allow you to do some very nifty things, but unless you’re exposing an interface to the larger world, they probably shouldn’t be the first thing you reach for. If you want to apply the same “function” to many different data types, then Protocols work really well. In particular if you need to
do things to nested data types, you can use recursion and protocols to do powerful transformations with minimal code.

KallDrexx

KallDrexx

A third thing you might want to compare with pattern-matching/Protocols are Behaviours: Rather than swapping what what kind of data-type is passed to a function, you are swapping what module a certain function is called on.

I’m pretty surprised I didn’t think to use behaviours for this actually . I already am using behaviours for serializing and deserializing messages, so it makes perfect sense that all message specific handling logic would go with the message itself, instead of creating a module whose sole purpose is to try and handle every single message type. I think I wasn’t thinking about behaviours because of TDD, as it was encouraging me to just write a bunch of tests against a single module’s function and check the result.

Behaviours are also interesting because in theory I should be able to do:

struct_module = Map.get(Message, :__struct__)
struct_module.handle(state)

That also gives me the benefit of code locality and discoverability that I am wary of with protocols.

I’ll have to think about this some more.

Qqwy

Qqwy

TypeCheck Core Team

Protocols are sort of an extension to pattern-matching:

  • Normal pattern-matching only allows the person writing ModuleX to add function clauses to a certain function.
  • Protocols allow both the person writing, as well as any people using ModuleX as dependency to add function clauses to one (or multiple) of ModuleX’s functions.

Which protocol-function-clause is used depends on the type of the first argument passed to the function, so in that way this extra freedom is somewhat bounded (but I have yet to find a case where this does not provide enough flexibility).

A third thing you might want to compare with pattern-matching/Protocols are Behaviours: Rather than swapping what what kind of data-type is passed to a function, you are swapping what module a certain function is called on. Behaviours are often used on modules that define a number of complex functions (often on a module that is run as a separate process/GenServer). These basically list a number of functions (including their typespecs) that a module that implements a certain behaviour has to define. When not following a Behaviour, a compile-time warning is shown.

Last Post!

KallDrexx

KallDrexx

Yep, that’s a huge reason why I chose Beam for this project :).

The Learn You Some Erlang book was pretty confusing about gen_fsm so I’ll have to revisit it but I guess that’s true. This part of the system really is a big FSM so I probably should understand the gen_fsm stuff proper.

Thanks!

Where Next?

Popular in Questions Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New

Other popular topics Top

KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36654 110
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

We're in Beta

About us Mission Statement