absg
absg

Reputation: 387

Pattern matching and setting values

I'm starting with elixir but I'm having some issues while using pattern matching.

Suppose I want to declare a map such as:

var = %{
    y: Float.parse("3.4"),
    z: Float.parse("7.8")
}

To achieve the following result:

var = %{
    y: 3.4,
    z: 7.8
}

Taking into account that Float.parse returns {floatVal, _}. how can I do this without declaring temporary variables?

Is code below the only way to achieve this?

var = %{
    y: Float.parse("3.4") |> elem(0),
    z: Float.parse("7.8") |> elem(0),
}

Upvotes: 0

Views: 205

Answers (1)

Dogbert
Dogbert

Reputation: 222080

Float.parse does not return just a float value since it allows the user to handle strings that are not valid float values without a try/catch expression. If you know the strings will contain only floats, you can do |> elem(0) to fetch the float value:

iex(1)> %{y: Float.parse("3.4") |> elem(0), z: Float.parse("7.8") |> elem(0)}
%{y: 3.4, z: 7.8}

A better way to do this is to use String.to_float/1 which will raise an informative error if the string is not a float:

iex(2)> %{y: String.to_float("3.4"), z: String.to_float("7.8")}
%{y: 3.4, z: 7.8}
iex(3)> %{y: String.to_float("3.4"), z: String.to_float("a7.8")}
** (ArgumentError) argument error
    :erlang.binary_to_float("a7.8")

If you do want to gracefully handle errors, you can use with as well:

iex(4)> with {y, ""} <- Float.parse("3.4"), {z, ""} <- Float.parse("7.8"), do: %{y: y, z: z}
%{y: 3.4, z: 7.8}
iex(5)> with {y, ""} <- Float.parse("3.4"), {z, ""} <- Float.parse("a7.8"), do: %{y: y, z: z}
:error

Upvotes: 2

Related Questions