[erlang-questions] is empty catch statement possible?

16 views
Skip to first unread message

Motiejus Jakštys

unread,
Feb 9, 2012, 1:37:03 PM2/9/12
to erlang-q...@erlang.org
Hello,
consider this macro:

-define(silent(Level, Expr), (fun() ->
__Lager_OldLevel = lager:get_loglevel(lager_console_backend),
try
fun() -> Expr end
catch
throw:'$__should_never_be_thrown' -> ok
after
leger:set_loglevel(lager_console_backend, __Lager_OldLevel)
end
end)()).


1) does it do what I expect? I want log level to be restored in _any_ case.
2) Is there a way to avoid the stub throw:Atom statement?

Thanks
Motiejus
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions

Motiejus Jakštys

unread,
Feb 9, 2012, 1:39:28 PM2/9/12
to erlang-q...@erlang.org
Whoops, a small mistake in code. Fixed version:

-define(silent(Level, Expr), (fun() ->
__Lager_OldLevel = lager:get_loglevel(lager_console_backend),

+ lager:set_loglevel(lager_console_backend, Level),


try
fun() -> Expr end
catch
throw:'$__should_never_be_thrown' -> ok
after
leger:set_loglevel(lager_console_backend, __Lager_OldLevel)
end
end)()).

Motiejus

Lukas Larsson

unread,
Feb 9, 2012, 1:46:07 PM2/9/12
to Motiejus Jakštys, erlang-q...@erlang.org
iirc you should be able to do:

try
something
after
io:format("hello after",[])
end.

Not sure how lager works, but if it keeps an external state for the
logging level it will not be reset if the process executing the try
catch is killed due to an exit msg.

Lukas

2012/2/9 Motiejus Jakštys <desir...@gmail.com>:

Konstantin Tcepliaev

unread,
Feb 9, 2012, 2:06:56 PM2/9/12
to Motiejus Jakštys, erlang-q...@erlang.org
Hello, Motiejus.

1. Yes, except that your code will return your Expr wrapped in zero arity fun, which is probably not what you want, though I'm not sure.
2. You can omit 'catch' clause entirely, leaving only 'try' and 'after'.

Also a couple of tedious notes: first, better be less javascriptish and replace your outer lambda with begin ... end, as that'll be a bit faster and a lot more readable, and second - avoid starting variable name with underscore when you're going to use its value somewhere, it'll save you from stupid debugging someday.

09.02.2012, 22:37, "Motiejus Jakštys" <desir...@gmail.com>:

Regards,
--
Konstantin

Motiejus Jakštys

unread,
Feb 9, 2012, 2:18:05 PM2/9/12
to Konstantin Tcepliaev, erlang-q...@erlang.org
On Thu, Feb 09, 2012 at 11:06:56PM +0400, Konstantin Tcepliaev wrote:
> Hello, Motiejus.
>
> 1. Yes, except that your code will return your Expr wrapped in zero
> arity fun, which is probably not what you want, though I'm not sure.

Yes, that was another mistake...

> 2. You can omit 'catch' clause entirely, leaving only 'try' and
> 'after'.

Cool. Not sure why didn't work before, when I tried that.

>
> Also a couple of tedious notes: first, better be less javascriptish
> and replace your outer lambda with begin ... end, as that'll be a bit
> faster and a lot more readable, and second - avoid starting variable
> name with underscore when you're going to use its value somewhere,
> it'll save you from stupid debugging someday.

Didn't know it's possible to do like that. Thanks!

Konstantin Tcepliaev

unread,
Feb 10, 2012, 2:17:47 AM2/10/12
to Motiejus Jakštys, erlang-q...@erlang.org
Hello again, Motiejus.

One more thing: macro variables' scope is not limited to the text of macro, so in a piece of code such as:

lager:set_loglevel(lager_console_backend, InitialLevel),
..
?silent(SLevel, Expr),
..
lager:set_loglevel(lager_console_backend, NewLevel), %% NewLevel /= InitialLevel
..
?silent(SLevel, OtherExpr), %% badmatch here!

..you'll get a badmatch error on your __Lager_OldLevel variable. Redefining your macro as a normal function would be a great solution.

09.02.2012, 23:18, "Motiejus Jakštys" <desir...@gmail.com>:

> On Thu, Feb 09, 2012 at 11:06:56PM +0400, Konstantin Tcepliaev wrote:
>
>>  Hello, Motiejus.
>>
>>  1. Yes, except that your code will return your Expr wrapped in zero
>>  arity fun, which is probably not what you want, though I'm not sure.
>
> Yes, that was another mistake...
>
>>  2. You can omit 'catch' clause entirely, leaving only 'try' and
>>  'after'.
>
> Cool. Not sure why didn't work before, when I tried that.
>
>>  Also a couple of tedious notes: first, better be less javascriptish
>>  and replace your outer lambda with begin ... end, as that'll be a bit
>>  faster and a lot more readable, and second - avoid starting variable
>>  name with underscore when you're going to use its value somewhere,
>>  it'll save you from stupid debugging someday.
>
> Didn't know it's possible to do like that. Thanks!
>
> Motiejus

Regards,
--
Konstantin

Motiejus Jakštys

unread,
Feb 10, 2012, 3:09:54 AM2/10/12
to Konstantin Tcepliaev, erlang-q...@erlang.org
2012/2/10 Konstantin Tcepliaev <f3...@f355.ru>:

> Hello again, Motiejus.
>
> One more thing: macro variables' scope is not limited to the text of macro, so in a piece of code such as:
>
> lager:set_loglevel(lager_console_backend, InitialLevel),
> ..
> ?silent(SLevel, Expr),
> ..
> lager:set_loglevel(lager_console_backend, NewLevel), %% NewLevel /= InitialLevel
> ..
> ?silent(SLevel, OtherExpr), %% badmatch here!
>
> ..you'll get a badmatch error on your __Lager_OldLevel variable. Redefining your macro as a normal function would be a great solution.

This is why I was initially wrapping the macro to the function.
"JavaScript"ish way makes sense in this case, so Lager_OldLevel will
be in a separate scope.

--
Motiejus Jakštys

Reply all
Reply to author
Forward
0 new messages