Struct without fields

One way to define a struct is to use a simple map with the __struct__ key

Let’s say we have a module StructWithoutFields

we could call

iex> %{__struct__: StructWithoutFields} |> is_struct()
true

This will be a struct but we won’t be able to call %StructWithoutFields{}

The next step I’d suggest is looking into the macro implementation like @sheharyarn suggested.

I left a lot of parts out in the following example but this might give you an idea

defmodule StructWithoutFields do
  @struct %{__struct__: __MODULE__}

  def __struct__(kv) do
    Enum.reduce(kv, @struct, fn {key, val}, map ->
      Map.replace!(map, key, val)
    end)
  end

  def __struct__() do
    @struct
  end
end

With that module you will already be able to call

iex> %StructWithoutFields{} |> is_struct()
true

If you haven’t read it yet I can really recommend reading Metaprogramming Elixir: Write Less Code, Get More Done (and Have Fun!) by Chris McCord
It goes into a lot of detail on how macros work and how basically a lot of elixir is build upon macros