-
Notifications
You must be signed in to change notification settings - Fork 20
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
Allowing bare :ok and :error values #66
Comments
Thoughts:
I have mellowed in my opinion on keeping everything strict. Caring about the details of typeclasses/monad is not a trait of the Elixir community, so working with what's around does make sense. I would accept option 3 now, module name can be anything. This could be released as 2.x and allow people to try it out. I don't think there is any fundamental problem with the proposal of working with bare atoms But I would like to be sure, buy having some test cases in the wild. Eventually if option 3 was a success I would probably suggest moving it over to the main API as a 3.0 release |
Are there any updates on this? If there's no one to work on the implementation, I can help contribute to it, a lot of functions in standard Elixir return bare :ok values. |
It may also make sense to allow more than 2 length tuples. I have found some functions doing this and I like returning longer tuples myself. Here's an example: iex(6)> :uri_string.parse("##")
{:error, :invalid_uri, '#'} (although this may be a bad example, since it doesn't return an ok-tuple on success) |
Context
I recently realised more and more code I'm writing in my day job is half-hearted error handling for which OK-style ~result monad would be the better solution.
At the same time, the main reason I don't introduce it to the codebase is that many of the functions in the system that are used just for their side-effects have a return value of
:ok | {:error, reason}
. Or, similarly, we're using standard library functions likeMap.fetch(map(), key()) :: {:ok, value()} | :error
.As much as I personally like OK, I can't really make an argument that all functions that don't return correctly formed 2-tuple results should be re-written or wrapped, just so that we can start using the library.
I believe the lack of ability to handle bare
:ok
and:error
values significantly impedes the widespread adoption of OK.Semantics
I believe wherever an
{:ok, term} | {:error, term}
is expected, an:ok
or:error
could be interpreted as{:ok | :error, nil}
. I can't think of a case where it would be really problematic.I imagine however you might not like the semantics change, I remember you being pretty committed to keeping it strict and there's a note about it in the readme. One could potentially make an argument that there might exist users for whom it is important that OK enforces the 2-tuple shape of the function returns.
Depending on the implementation we can keep or not keep the backwards compatibility
Implementation options
Note, I haven't carefully read and thought about the current implementation, some of these might be harder to execute on than I imagine.
1. Just change the semantics, keep the interface as it is.
I think I might be up for that, but I wouldn't be surprised @CrowdHailer and others weren't happy with that.
Would probably mean releasing OK 3.0
2. Create lenient versions of all macros / functions in
OK
moduleI'm not sure what the right names for the new functions would be. Also, transitioning from strict to lenient OK in any project would be an ugly change.
3. Create a lenient version of the
OK
moduleThe module would basically rewrite whatever
OK
does with the new semantics, with as much code re-use as possible. The implementation would probably end up a bit ugly, but using it and transitioning fromOK
to "lenientOK
" would probably be painless.I think something like this would work:
4. Some clever option with
use
I'm not sure how that would look like in its best version. Also, from my limited understanding of Elixir macros, I feel like having
use
in many modules could have a bad impact on compilation time, as it would be independently executed for each of the modules. It's just my assumption though, probably worth confirming.Also, personally I like to not use
use
if I can help it, it introduces unnecessary magic that might be hard to debug.5. Something else
There's probably other options, I can't think of any good ones right now, but I'm open to suggestions.
Closing notes
I think I like (1), if that's not an option, I think (3) could give a good end result.
As usual, I'd be down for doing the implementation if we decide on going ahead with any of the options and it looks viable.
The text was updated successfully, but these errors were encountered: