exceptional
exceptional copied to clipboard
Add new syntax, fix credo
I do apologize for combining a new syntax PR with an updated Credo PR, but fixing Credo 'as' I was making the new syntax was greatly useful since it stopped the many warnings I was getting on every-full-compile. ^.^;
In addition to the credo warning fixes this adds a new construct named block
as well as an auto-raising version of it called block!
.
The general pattern of block
is like (copied from the docs added for it):
Block
Kind of a combination of Elixir's normal
with
special form in addition to a monad-styledo
pipeline.This automatically-wraps every return value with
normalize
.block do a <- {:ok, 2} b = a * 2 c <- {:ok, b * 2} c * 2 end #=> 16 block do a <- {:ok, 2} b = a * 2 _ = 42 c <- {:error, "Failed: #{b}"} c * 2 end #=> %ErlangError{original: "Failed: 4"} conversion_fun = fn {:blah, reason} -> %ErlangError{original: "Blah: #{reason}"} e -> e end block conversion_fun: conversion_fun do a <- {:ok, 2} b = a * 2 _ = 42 c <- {:blah, "Failed: #{b}"} c * 2 else _ -> {:error, "unknown error"} end #=> %ErlangError{original: "unknown error"} block! do a <- {:ok, 2} b = a * 2 _ = 42 c <- {:error, "Failed: #{b}"} c * 2 end #=> ** (ErlangError) Erlang error: "Failed: 4"
Don't merge just yet (if you even want to merge it), this is for discussion at this point.
For note, everything should be piecemeal in different commits if you wish to review it more easily.
And for note, I made this because I really hate elixir's normal with
special form (nasty comma's ^.^;), plus hey, normalized decomposition! :-)
I guess it might be ready to merge now if you think (and of course, if you want it).
I am thinking of adding an option to return a tagged_tuple as well, if so should it be an option or another name for it (block?
maybe? I'm not sure about overriding that context though...).
Although I guess the user could just pipe it into the tagged tuple maker though...
What is your thought on adding another expression type of a <~ b
that is like <-
but auto-wraps in a try/catch?
Also, should I change :non_match = 42
to instead of letting it throw a match exception instead return the non-matched value? That would make it like <-
but without the unwrapping/normalization property, which I think might be better (but would make it different from how with
acts, which just raises a MatchError
too when there is no match on a =
call, it only decorates <-
calls like I am currently).
Hmm, maybe <~
could be a non-normalization version of <-
, or maybe that could be swapped? But if I do that then what would be a good operator for auto-try/catch?
Hmm, yeah I'm leaning to having <-
be like how with
uses it now, just a simple set or return on failed match, and a <~
be a normalized call... Eh... but simplicity is better so perhaps it should remain as it is now... Thoughts? >.>
Woah, didn't see ya there! Looking now 👀
Don't merge just yet (if you even want to merge it), this is for discussion at this point.
You know, I like it! We'll probably see people abusing block do
a bit, and wondering where the performance hit is (since the behaviour is so automatic), but my opinion is "with great macros comes great responsibility" 😉
I'm generally a fan. Did you have any specific concerns, @OvermindDL1 ?
What is your thought on adding another expression type of a <~ b that is like <- but auto-wraps in a try/catch?
I'd maybe name them as separate block types or with options? We should be careful with overloading the tilde operators too much. There's only so many, and we want the code to remain clearish. I already feel bad introducing so many operators and in so many different packages 😬
So yeah, I'd leave the <-
, but any change in behaviour could be made an option to let people opt in/out with a sensible default if nothing is specified. Thoughts?
I'm generally a fan. Did you have any specific concerns, @OvermindDL1 ?
Mostly just what I mentioned above, which is pure usage issues, the code seems sound from my testing. :-)
So yeah, I'd leave the <-, but any change in behaviour could be made an option to let people opt in/out with a sensible default if nothing is specified. Thoughts?
That is what I was leaning to. It is pretty trivial to add more options to the block for more or special functionality and this seems a good, simple, unsurprising, and easy to use base. :-)
This has languished for WAY TOO LONG. I need to dive back into this one; I'll have a but of time soon over the holiday break. Deepest apologies for how long this has taken 🙏
I wouldn't be remotely surprised if there were corner cases not caught so a good test suite would be very nice!