Struct Embedding in Elixir
In Elixir, we can achieve similar functionality to struct embedding using composition and delegate. Here’s how we can translate the concept:
defmodule Base do
defstruct [:num]
def describe(%{num: num}) do
"base with num=#{num}"
end
end
defmodule Container do
defstruct [:base, :str]
defdelegate describe, to: :base
end
defimpl String.Chars, for: Container do
def to_string(%{base: %{num: num}, str: str}) do
"co={num: #{num}, str: #{str}}"
end
end
defmodule Main do
def run do
co = %Container{
base: %Base{num: 1},
str: "some name"
}
# We can access the base's fields directly on co
IO.puts("#{co}")
# Alternatively, we can spell out the full path
IO.puts("also num: #{co.base.num}")
# We can call the describe function which is delegated to Base
IO.puts("describe: #{Container.describe(co)}")
# In Elixir, we don't need to explicitly declare interfaces
# The protocol system provides similar functionality
IO.puts("describer: #{Container.describe(co)}")
end
end
Main.run()In this Elixir version:
We define a
Basestruct with anumfield and adescribefunction.We define a
Containerstruct that includes abasefield (which will be aBasestruct) and astrfield.We use
defdelegateto delegate thedescribefunction to thebasefield. This is similar to embedding in Go, allowingContainerto useBase’sdescribefunction.We implement the
String.Charsprotocol forContainerto allow easy printing of its contents.In the
Mainmodule, we create aContainerinstance and demonstrate how to access fields and call the delegateddescribefunction.Elixir doesn’t have interfaces in the same way as Go, but its protocol system serves a similar purpose. In this case, any struct that implements a
describefunction could be used interchangeably where a “describer” is expected.
When you run this program, you’ll get output similar to:
co={num: 1, str: some name}
also num: 1
describe: base with num=1
describer: base with num=1This example demonstrates how Elixir can achieve functionality similar to Go’s struct embedding through composition and delegation.