Generics in Elixir
Elixir introduced protocols as a way to achieve polymorphism, which can be used to implement behavior similar to generics in some cases. However, Elixir doesn’t have a direct equivalent to Go’s generics. We’ll use protocols and other Elixir features to demonstrate similar concepts.
defmodule Generics do
# Elixir doesn't have a direct equivalent to Go's generics,
# but we can use protocols to achieve similar functionality.
# Here's an example of a protocol that can work with any
# enumerable type.
defprotocol Findable do
@doc "Finds the index of an element in an enumerable"
def find_index(enumerable, element)
end
# Implement the protocol for List
defimpl Findable, for: List do
def find_index(list, element) do
Enum.find_index(list, &(&1 == element))
end
end
# Implement the protocol for other enumerables
defimpl Findable, for: Enumerable do
def find_index(enumerable, element) do
enumerable
|> Enum.with_index()
|> Enum.find(fn {e, _} -> e == element end)
|> case do
{_, index} -> index
nil -> -1
end
end
end
# Define a custom linked list
defmodule LinkedList do
defstruct [:head, :tail]
def new, do: %LinkedList{}
def push(%LinkedList{head: nil, tail: nil} = list, value) do
new_node = %{value: value, next: nil}
%{list | head: new_node, tail: new_node}
end
def push(%LinkedList{tail: tail} = list, value) do
new_node = %{value: value, next: nil}
%{list | tail: %{tail | next: new_node}, tail: new_node}
end
def all_elements(%LinkedList{head: head}) do
all_elements(head, [])
end
defp all_elements(nil, acc), do: Enum.reverse(acc)
defp all_elements(node, acc), do: all_elements(node.next, [node.value | acc])
end
def main do
s = ["foo", "bar", "zoo"]
# Using our Findable protocol
IO.puts("index of zoo: #{Findable.find_index(s, "zoo")}")
# Create and use our custom LinkedList
list = LinkedList.new()
|> LinkedList.push(10)
|> LinkedList.push(13)
|> LinkedList.push(23)
IO.puts("list: #{inspect(LinkedList.all_elements(list))}")
end
end
Generics.main()In this Elixir example:
We define a
Findableprotocol that’s similar to theSlicesIndexfunction in the Go example. This protocol can be implemented for different types.We implement the
Findableprotocol forListand otherEnumerabletypes.We create a custom
LinkedListstruct to demonstrate a generic data structure. In Elixir, we don’t need to specify type parameters as it’s a dynamically typed language.The
mainfunction demonstrates the usage of ourFindableprotocol andLinkedListstruct.
To run this program, save it as generics.exs and use:
$ elixir generics.exs
index of zoo: 2
list: [10, 13, 23]Note that Elixir’s approach to polymorphism and data structures is quite different from Go’s. Elixir uses protocols and pattern matching to achieve similar results to generics in statically typed languages.
Comments powered by Disqus