[Nix-dev] Re: Proposal: tryCatch function

Andres Loeh andres.loeh at googlemail.com
Tue Jan 6 20:41:02 CET 2009


>> Regarding tryCatch: as far as I understood it, it doesn't introduce any
>> impurity, so I don't find it particularly problematic to add.
>
> The impurty problem is due to the problem that anything can come out
> the catch function.
>
> tryCatch ((throw "foo") + (throw "bar")) (msg: msg) == "foo" OR "bar" ???
>
> In the case the throw statement does not brake the evaluation (and
> possibly change the return value).

This only arises if the handler gets the message. But as I said before,
I don't think it would be problematic to fix the evaluation order of arguments
to functions. Most languages do, and I don't see there being a huge benefit
in it staying unspecified. (Even if the semantic order is fixed, the
arguments could still be evaluated in parallel.)

> tryRethrow does not have this issue because it is just a function
> which handles the error computation, but at the end an error will be
> raised.

It has the same issue, we just care less. The error message being produced
is as much part of the semantics than the result value. It's a personal choice
to say that we identify all errors to be the same thing and don't care.

>> But I doubt
>> its usefulness given the lazy nature of the language and the escaping
>> issues.
>
> I don't see why the escaping with the laziness can broke this clean
> "stack trace".

Saying that I "doubt the usefulness" is not the same as saying that it breaks
something. As others (or even you?) have pointed out before, you only
evaluate the body of the try to so-called weak head normal form. I.e., you stop
if you reach a function abstraction, at you probably should stop as well if you
reach a data constructor (such as an attribute set). Any exceptions hidden in
the body of a function or hidden in a value of an attribute in an attribute set
escape. In strict first-order languages, try-catch is used around rather large
blocks, and you can be certain to catch any exception rising within. This
property doesn't hold for Nix. That's why I'd assume that use of the construct
might be less useful than hoped for.

>> Plus, I think it sends the wrong message, because it
>> encourages the use of
>> exceptions (throw), which are impure already, and I don't like that very
>> much.
>
> As you said, this is only used for error computation, then this is a
> kind of premature exit.  So, yes "throw" is impure but this is just a
> short way to say that something goes wrong.
>
>> I think we should strive for ways to be able to program with as few
>> as possible uses of throw.
>
> True, but we still need some because the stack trace just give you the
> function name, the lines but not the argument used to compute your
> function or something more talkative.

Eelco has pointed out that one way to do that would be to just pass more
context information down to the place where throw is called. I haven't yet
seen a good argument why introducing a new primitive is better than that.
What's the typical use case you have in mind for this construct?

Cheers,
  Andres



More information about the nix-dev mailing list