Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

`catch` should be it's own macro #594

Closed
devinus opened this Issue Oct 29, 2012 · 7 comments

Comments

Projects
None yet
2 participants
Contributor

devinus commented Oct 29, 2012

So that I can do an inline catch like in Erlang:

case catch foo() do
end

bar = catch bar()
Owner

josevalim commented Oct 29, 2012

I never understood the benefit of those over the usual try/catch approach. Can you provide an example?

In any case, if we decided to add this, it could be done as a catch! macro (catch on its own is taken).

Contributor

devinus commented Oct 29, 2012

@josevalim Sure, an example from some Erlang code:

        Rpc = case catch zuul_salieri_json:to_term(Body) of
            {'EXIT', _} ->
                throw(parse_error);
            {incomplete, _} ->
                throw(parse_error);
            Term ->
                #rpc{
                    jsonrpc = ?get(jsonrpc, Term),
                    id = ?get(id, Term),
                    method = ?get(method, Term),
                    params = ?get(params, Term)
                }
        end,
Owner

josevalim commented Oct 29, 2012

Yeah, this example does not convince me though. :) It does not add much over try/catch (see below) and catch! has the downside of catching everything, so it is an idiom I would avoid.

try do
  :zuul_salieri_json.to_term(body)
catch
  { :incomplete, _ } ->
    throw(:parse_error)
  term ->
    RPC[
      jsonrpc: get(:jsonrpc, term),
      id: get(:id, term),
      method: get(:method, term),
      params: = get(:params, term)
    ]
  _, _ ->
    throw(:parse_error)
end

My general impression is that catch is a mechanism added in Erlang but it was super seeded by try/catch in later Erlang releases.

Contributor

devinus commented Oct 29, 2012

@josevalim uhh the point is to catch everything! It's easier than:

bar = try do
  foo()
catch
  anything -> anything
end

# when you should be able to just do:
bar = catch! foo()

Also the first one doesn't even capture what was caught.

Owner

josevalim commented Oct 29, 2012

@devinus except that you never do as you did above, right? You always end up matching against the returned value to extract information, so you end up with case + catch which is similar to try. And yes, sometimes you may want to catch everything, but those cases are rather rare. For example, do you really care about catching exits in :zuul_salieri_json.to_term(body)? Is there a chance it could hide potential bugs?

Contributor

devinus commented Oct 29, 2012

@josevalim In your example, the incomplete is not thrown, it is potentially returned by to_json. You cannot catch it. This example doesn't work. You'd need a case clause in the try block as well, making the code more complicated.

Owner

josevalim commented Oct 30, 2012

@devinus good point. this is actually another annoyance i have with catch!, because it mixes returned with thrown results. In any case, it is easy to restructure that example to either call a local function to handle the result or to handle it later in case. catch Expr muddies too many concerns in my opinion which makes it rarely worth to use. :S

@josevalim josevalim closed this Oct 30, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment