Now that bertschi mentioned Haskell and side-effects, I noticed that the
problem we have here totally looks like a monad:
we have several steps of side-effecting computation, and each of them can
fail, and when this happens you want to handle the failure while keeping
the previous bindings.
Now, when it comes to handling Java exceptions in a monadic way, we can
look at the Try monad in Scala, that is exactly what we are searching for.
We have several libraries that implement monadic sugar in Clojure, and
`cats` [1] implements the try monad [2].
Example usage with `mlet` (monadic let, aka `do` in Haskell):
=> (require '[cats.core :as m])
nil
=> (require '[cats.monad.exception :as exc])
nil
=> (m/mlet [a (exc/try-on 1)
b (exc/try-on a)] ;; a is visible in b scope of course, as in
standard let
(m/return (str "a: " a ", b: " b)))
#<Success "a: 1, b: 1">
boot.user=> (m/mlet [a (exc/try-on 1)
b (exc/try-on (+ 1 nil))] ;; when you get an exception
it blows up
(m/return (str "a: " a ", b: " b)))
#<Failure #error {
:cause nil
:via
[{:type java.lang.NullPointerException
:message nil
:at [clojure.lang.Numbers ops "Numbers.java" 1013]}]
:trace
...
=> (m/mlet [a (exc/try-on 1)
b (exc/try-or-else (+ 1 nil) a)] ;; but you have the a binding
also in case of exception
(m/return (str "a: " a ", b: " b)))
#<Success "a: 1, b: 1">
[1]: https://github.com/funcool/cats
[2]: http://funcool.github.io/cats/latest/#exception
Cheers,
Fabrizio
On Mon, Oct 2, 2017 at 4:39 AM, Didier <[email protected]> wrote:
> I've seen this, I was still curious if the reason I was facing the issue
> was that let is simply the wrong tool for my use case or not.
>
> If let is the correct tool, I would propose that clojure.core should had a
> try/catch where the catch is in scope of the try. I feel the reason this is
> contrived is accidental complexity due to limitations of Clojure. In Java,
> this isn't an issue, because you're variables would be mutable:
>
>
> Object a;
> Object b;
> Object c;
> try {
> a = doA(..);
> b = doB(.., a, .., .., ..);
> c = doC(.., .., a, .., b, ..);
> } catch {
> // The catch is in scope of a,b,c.
> }
>
> Which I feel I can't think of any way in Clojure to do this, which does
> not add accidental complexity. In that, there's nothing to the actual
> problem which requires say the complexity of a let inside a let, a
> try/catch around each steps, binding atoms, delays, promise, volatile and
> then setting them inside the try, etc. All these seems to me like Clojure
> just adds some accidental complexity to this common use case.
>
> What do others think?
>
>
> On Saturday, 30 September 2017 16:42:48 UTC-7, Marcus Magnusson wrote:
>>
>> I've used try-let (link below) for this, it's worked great!
>>
>> https://github.com/rufoa/try-let
>>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to [email protected]
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.