Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Print a variable name in Elixir

Warning: this is an attempt to be clever. I am aware that I probably should just leave it readable, but that doesn't mean I don't want to know how to be clever :-P

I have something like this (contrived example):

def glue(%{"alpha" => alpha, "beta" => beta}) do
  cond do
    alpha && beta ->
      alpha <> beta
    alpha ->
      IO.puts("oops, you forgot to give me alpha!")
    true ->
      IO.puts("oops, you forgot to give me beta!")
  end
end

but would like to instead have:

def glue(%{"alpha" => alpha, "beta" => beta}) do
  cond do
    alpha && beta ->
      alpha <> beta
    true ->
      something
      |> need_field()
  end
end

defp need_field(something) do
  IO.puts("oops, you forgot to give me " <> something)
end

Is there a clever way to get the name of the empty variable?

I was thinking along the lines of somehow using alpha || beta to get the populated one, then print the name of the other one, but I can't quite seem to get there.

like image 514
TrivialCase Avatar asked Aug 06 '26 20:08

TrivialCase


1 Answers

You have to be careful with matching on map keys. If the map does not contain the key, then your function head will not match. You could do this:

def glue(%{"alpha" => alpha, "beta" => beta} = map) do
  cond do
    alpha && beta ->
      alpha <> beta
    true ->
      need_field(map)
  end
end

defp need_field(map) do
  Enum.each(map, fn 
    {k, nil} -> IO.puts "You forgot to give me #{k}"
    _ -> nil
  end
end

Now, if you expecting the map to be missing the field, then you could add a second function clause:

def glue(map) do
  Enum.each ~w(alpha beta), fn key -> 
    if map[key], do: nil, else: IO.puts("You forgot to give me #{key}")
  end
end

Here is the complete solution if its a map.

def glue(%{"alpha" => alpha, "beta" => beta} = map) do
  cond do
    alpha && beta ->
      alpha <> beta
    true ->
      need_field(map)
  end
end
def glue(map) do
  Enum.each ~w(alpha beta), fn key -> 
    if map[key], do: nil, else: IO.puts("You forgot to give me #{key}")
  end
end

defp need_field(map) do
  Enum.each(map, fn 
    {k, nil} -> IO.puts "You forgot to give me #{k}"
    _ -> nil
  end
end

If the input is a struct, then you don't have to worry about the default clause since a struct has to have all the keys. In this case, you can get the keys from the struct by

map
|> Map.from_struct 
|> Enum.each(...
like image 113
Steve Pallen Avatar answered Aug 09 '26 08:08

Steve Pallen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!