elt547

elt547

What is the most idiomatic way to construct structs with complex default values?

I have a struct representing a session request with only two fields, email and bytes. Basically the struct should either be passed around as immutable or created with a default value as a function return value. I have a function random_bytes which I want to be the default value of bytes.

Since you can’t declare it like this:
defstruct [:email, bytes: random_bytes()]

Someone suggested making a “new” function:

def new(email) do
  %__MODULE__{email: email, bytes: random_bytes()}
end

But to me this feels very non-idiomatic. It feels like shoehorning an object oriented pattern into a functional language.

What is the best way to build a strict with a complex default value in elixir?

Most Liked

tomkonidas

tomkonidas

why not add another function to handle that?

def with_random_bytes(%Email{} = email) do
  Map.put(email, :bytes, random_bytes())
end

Then in your context or anywhere else you need it can always just call it like:

%Email{}
|> Email.with_random_bytes()
|> ...
zachallaun

zachallaun

There’s no difference, really.

def with_random_bytes(struct) do
  Map.put(struct, :bytes, random_bytes()
end

…

%MyStruct{email: email}
|> MyStruct.with_random_bytes()

However, I think new is the way to go. Don’t overcomplicate things. Document that new structs should be created using the initializer in order to set dynamic defaults.

msimonborg

msimonborg

Are Map.new, Range.new, and MapSet.new non-idiomatic? :slight_smile:

100% agree, Session.new(email) or Session.new(opts) with documentation feels right IMO.

tomkonidas

tomkonidas

The thing is attrs is an Enumerable.t(), so it can be a map or a keyword. So that is why i do it after i create the struct.

But yea very valid if you want to have the two functions as you showed

tomkonidas

tomkonidas

We can even mix and match both solutions:

def new(attrs) do
  __MODULE__
  |> struct(attrs)
  |> maybe_with_random_bytes()
end

defp maybe_with_random_bytes(%{bytes: nil} = struct) do
  Map.put(struct, :bytes, random_bytes())
end

defp maybe_with_random_bytes(struct), do: struct

Where Next?

Popular in Questions Top

Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
LegitStack
I’m hoping you guys can give me some general advice and perhaps code examples if you’re feeling up to it. I’m very interested in Elixir,...
New
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
makeitrein
Hey all, just started picking up Elixir last week and am writing a scraper as a learning project. Baby step #1 is extracting the number ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New

Other popular topics Top

peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 49522 488
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

We're in Beta

About us Mission Statement