-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Surprising return from Result.map({:ok, _}, nil)
#7
Comments
A full example of the issue I have is here: message_map_r = {:ok, %{"Timestamp" => "2022-01-06T14:46:56.387201Z", "Value" => nil}
value_r =
message_map_r
|> Result.map(&Map.get(&1, "Value"))
|> Result.default_error("Value is missing from map.")
The above code returns (I appreciate that the |
It could be that the intention isn't communicated clearly enough in the documentation, but the general idea is that you're either working with nillable values, or you're working with tagged Results. If you enter a Result pipeline, then your intention is to avoid / short-circuit To me, it seems that your example behaves safely - it detects a If your intention is to provide different behaviour depending on whether {:ok, %{"Timestamp" => "2022-01-06T14:46:56.387201Z", "Value" => nil}}
|> Result.then(&Map.fetch(&1, "Value"))
|> Result.error_map("Value is missing from map.")
|> Result.none_then(nil)
# => {:ok, nil} As a result, the desire to return |
Actually, the |
I can see where you're coming from, but my example is also an example of where tagged tuples shine -
|
For me, the problem is that I don't understand the meaning of "I have the value of nil". Nil as a concept means "no value". It's not an error, but it's not a value either. It seems to me that you're interested in two maybe-values here - the presence of the key, and the value of the key, where a missing key is an error. Essentially, the map itself is of type {:error, "The key is missing."}
{:ok, :none}
{:ok, {:some, 123}} This is certainly closer to what Rust does. The traditional approach in Elixir, of course, is to use The advantage of forcing a pattern match (e.g. The only real difference with {:ok, :none} | {:ok, {:some, any()} | {:error, any()}
Into this, mostly for convenience (and also because we can't rely on strict types to help enforce the nested pattern): :none | {:ok, any()} | {:error, any()} |
Well spotted :) That actually makes me a bit uncomfortable. I'd be tempted to add a I wonder if {:ok, nil}
|> Result.normalize()
# => :none
{:ok, nil}
|> Result.none_then("hello")
# => "hello" Which is a bit safer, but could also cause confusion: {:ok, nil}
|> Result.then("hello")
# => {:ok, nil) |
I know this library is mostly a mashup of two different functional concepts - maybe values and tagged errors.
Saying that, it looks like there isn't a way of handling "I know what the value is, and it is
nil
" - I was quite surprised that{:ok, 1} |> Result.map(nil)
returns:none
.I can see that's even in the docs, but I think it's a flaw in the design, and even contradictory. From what I can see, no other calls to
Result.map
change the outer tuple.The text was updated successfully, but these errors were encountered: