desmond

desmond

Multiple callbacks for same function, different arguments

My application has many serializers for turning structs into something suitable for clients. These serializers have many serialize/1 functions defined to handle the nil case, list case, and finally the struct itself:

defmodule MyApp.ItemSerializer do
  def serialize(nil), do: nil
  def serialize(items) when is_list(items) do
    Enum.map(items, serialize/1)
  end

  def serialize(item) do
    %{
          # ...
        }
  end
end

I’d like to have a @behaviour MyApp.Serializer directive to guarantee that individual implementations follow the contract of implementing all the serialize/1 functions. The problem is, it looks like callbacks only respect one function implementation, and creating many callbacks with the same function name but different typespecs does not help.

Is this the expected --ahem-- behavior of callbacks?

Most Liked

NobbZ

NobbZ

Why don’t you make it a protocoll? Then you could implement the list-case once in a defimpl X, for: List, the nil in defimpl X, for: Atom, while having discrete defimpl X, for: Y for your different structs.

michalmuskala

michalmuskala

Here’s an idea - use a protocol with two callbacks - serialize_v1 and serialize_v2. For implementations where those are close enough or even the same, it’s pretty easy to delegate to a common implementation.

tty

tty

This is linked to how functions are differentiated in the BEAM. Functions are differentiated by the module they reside in, their name and arity (number of arguments the function accepts). As such serialize/1 is the same function and the various function clauses a contraction of an if-else.

If having these 3 cases are import the define the 3 different functions in the behaviour individually e.g. serialize_nil/1, serialize_lists/1, serialize_item/1. The behaviour can auto-generate a serialize/1 which calls the relevant callbacks.

If you have many different structs perhaps look into using Protocols.

Last Post!

OvermindDL1

OvermindDL1

Or use a protocol per version that can delegate to the lower version for the parts that are the same.

Yep, precisely my second suggestion. ^.^

Where Next?

Popular in Questions Top

electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
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
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

Other popular topics Top

Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54996 245
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 49134 226
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40082 209
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 44608 311
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

We're in Beta

About us Mission Statement