The %URL{}
version expands the struct definition at compile-time. You can demonstrate this with the @compile :S
flag:
defmodule Foo do
defstruct [:bar, :baz, huh: 69]
end
defmodule Bar do
@compile :S
def literal_version(x) do
%Foo{bar: x, baz: 42}
end
def struct_version(x) do
struct(Foo, bar: x, baz: 42)
end
end
Running elixir
on this file fails, but also produces a new file with the extension .S
that has BEAM assembly in it.
literal_version
compiles to an explicit map operation:
{function, literal_version, 1, 11}.
{label,10}.
{line,[{location,"struct_demo.ex",8}]}.
{func_info,{atom,'Elixir.Bar'},{atom,literal_version},1}.
{label,11}.
{put_map_assoc,{f,0},
{literal,#{}},
{x,0},
1,
{list,[{atom,'__struct__'},
{atom,'Elixir.Foo'},
{atom,bar},
{x,0},
{atom,baz},
{integer,42},
{atom,huh},
{integer,69}]}}.
return.
Versus the struct
version:
{function, struct_version, 1, 13}.
{label,12}.
{line,[{location,"struct_demo.ex",12}]}.
{func_info,{atom,'Elixir.Bar'},{atom,struct_version},1}.
{label,13}.
{test_heap,5,1}.
{put_tuple2,{x,0},{list,[{atom,bar},{x,0}]}}.
{put_list,{x,0},{literal,[{baz,42}]},{x,1}}.
{move,{atom,'Elixir.Foo'},{x,0}}.
{line,[{location,"struct_demo.ex",13}]}.
{call_ext_only,2,{extfunc,'Elixir.Kernel',struct,2}}.