Curious case of ‘in’ in Elixir
tl;dr
'in' is usually used with list or range. But here we
1. Implement Enumerable for another data type to use ‘in’.
2. Define macro with ‘in’ to improve readability.
Don’t try this at home
Just kidding, we can use this, but we might introduce unnecessary bugs in the code and might make the code unreadable as this is not widely practiced. Let’s do this as an experiment to know more about Elixir.
Using ‘in’ with string
Let’s try to find whether a substring is present inside a string.
"lix" in "Elixir"
I want this to give back ‘true’. But it errors as
** (Protocol.UndefinedError) protocol Enumerable not implemented for "ab" of type BitString
(elixir 1.10.4) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.10.4) lib/enum.ex:166: Enumerable.member?/2
(elixir 1.10.4) lib/enum.ex:1682: Enum.member?/2
So let’s implement Enumerable for String.
Now If we run
"lix" in "Elixir"
in iex, it will return ‘true’.
Success.
History detour
This curiosity started while I was debugging a code related to ‘from’ in ecto query. How ecto allows us to write code like
from(c in City, select: c)
Click on the `(macro) </>` to reach the Elixir codebase which implements this.
Let’s implement a shorter form.
Define macro with ‘in’
we can import this module and use as having("lix" in "Elixir") |> do_something()
. We can use the result of ‘having’ function further.This is how ‘in’ is added in ecto to improve readability.