Erlang throw statement not working in a function handler - erlang

I am trying to throw an error inside a function handler and catch it outside. It works fine if the handle is created localy. If I export the function and access it by its module name I get an {error,badarg}.
-module(mymodule).
-export([myfun/1]).
myfun(Any) -> throw(Any).
mytestfun1() ->
try
FunHandler=fun myfun/1,
FunHandler("myerr")
catch
W:E -> {W, E}
end.
% returns {throw,"myerr"} as it should
mytestfun2() ->
try
FunHandler=fun mymodule:myfun/1,
FunHandler("myerr")
catch
W:E -> {W, E}
end.
% returns {error,badarg} instead
I absolutely do not understand why this happens. Anybody got an idea?

This is a bug of the Eclipse IDE Erlide. In its debug mode it replaces all function handles. In this case it does something wrong.
I posted the Bug under:
http://sourceforge.net/tracker/?func=detail&aid=3373292&group_id=58889&atid=489191

Related

How can I get Dialyzer to accept a call to a function that intentionally throws?

I have a function that intentionally throws when its first argument is the atom throw.
A simplified version of this code is:
-module(sample).
-export([main/1, throw_or_ok/1]).
main(_Args) ->
throw_or_ok(throw).
throw_or_ok(Action) ->
case Action of
throw -> throw("throwing");
ok -> ok
end.
Dialyzer errors on the call to throw_or_ok:
sample.erl:7: The call sample:throw_or_ok
('throw') will never return since it differs in the 1st argument from the success typing arguments:
('ok')
Adding specs doesn't help, the error message is the same:
-module(sample).
-export([main/1, throw_or_ok/1]).
-spec main(_) -> no_return().
main(_Args) ->
throw_or_ok(throw).
-spec throw_or_ok(throw) -> no_return(); (ok) -> ok.
throw_or_ok(Action) ->
case Action of
throw -> throw("throwing");
ok -> ok
end.
How can I get Dialyzer to accept calls to throw_or_ok/1 that are guaranteed to throw?
Unfortunately there is currently no clean way to mark this as acceptable for Dialyzer via specs.
Perhaps you can use an ignore warning annotation, however.
Looks like if will put throw it will never return, if will put ok the pattern will never match with throw. See topic with similar issue. The logic of main/1 need to change, eg:
main(Args) ->
MaybeOk = case Args of
0 -> throw;
_ -> ok
end,
throw_or_ok(MaybeOk).
OR
main(_Args) ->
throw_or_ok(_Args).

Erlang How to mix try catch with if

I'm very new in Erlang.
I want to make function to check ban word.
But I got syntax errors..
How to use try catch with if else statement?
check_banword(Word, BlackWord) ->
try
Res = string:rstr(Word, BlackWord),
if Res > 0 ->
true;
true ->
false
catch
false
end.
Two problems in the code:
Missing end after if
Catch syntax is incorrect, catch matches exceptions to values, you cannot have just a value there.
The code with changes enabling it to compile looks like
check_banword(Word, BlackWord) ->
try
Res = string:rstr(Word, BlackWord),
if
Res > 0 ->
true;
true ->
false
end
catch
_ -> false
end.
In this case, you don't actually need the if, you can use try with patterns and guards. When used in this way, try looks like a case expression with a catch section at the end. (Note that only the part between try and of is "protected" by the catch - in this case, it doesn't make any difference because the rest of the code cannot raise an error.)
Also note that you need to specify what type of exception you want to catch, one of error, exit and throw. If you don't specify the type of exception, it defaults to throw - and that's not what you want here, since string:rstr never throws anything, it can only raise errors if the arguments are of an incorrect type.
So that would be:
check_banword(Word, BlackWord) ->
try string:rstr(Word, BlackWord) of
Res when Res > 0 ->
true;
_ ->
false
catch
error:_ -> false
end.
And there is a wider question: should you actually use try here? If an error occurs in this function, it means that the arguments were not strings, and that is the caller's responsibility. Since there isn't anything that this function can do to fix the problem, I'd say that it shouldn't catch the error but let it propagate to the caller. (This is known as Erlang's "let it crash" philosophy.)

spawn_link is starting an infinite loop, but does not return?

I have an init function which I call start_server:
start_server() ->
spawn_link(game_loop(0,0)).
The purpose is to start a new process that begin to loop and waiting for someone to send a message there:
game_loop(X,Y) ->
receive
{move, left} ->
tell_client(X+1,Y),
game_loop(X+1,Y);
{move, right} ->
tell_client(X-1,Y),
game_loop(X-1,Y)
end.
My thaught was that start_server would return the Pid so that I could write something like this in the Erlang terminal:
> Server = server:start_server().
And then use the variable Server to handle the servers via functions like:
move_left(Pid) ->
Pid ! {move, left}.
But that does not work since start_server() never returns, why is that?
The function spawn_link/1 takes a function as an argument. But in your code you dont pass a function into it:
start_server() ->
spawn_link(game_loop(0,0)).
That sample means that the function game_loop/2 will be called first and after it returns spawn_link/1 will be called with an argument which is a result of calling of game_loop/2. But your function game_loop/2 implements infinite loop so it will never returns and so spawn_link/1 will never be called. If we even assume that game_loop/2 returns it must return a function to call spawn_link/1 properly, otherwise an exception will rise.
To do what you want you should pass game_loop/2 as a function into spawn_link/1:
start_server() ->
spawn_link(fun () -> game_loop(0,0) end).

Shell.Exec in FAKE

I found this function Exec here http://fsharp.github.io/FAKE/apidocs/fake-processhelper-shell.html.
Target "UpdateTools" (fun _ ->
Exec "cmd"
)
But I keep getting this error, when I try to run it: "The value or constructor 'Exec' is not defined".
I'm new to FAKE and have not used F#, so forgive me if this should be obvious.
Can someone tell me why this api is not accessible like that?
The documentation is documenting class Shell. That means, you need to call it like:
Target "UpdateTools" (fun _ ->
ignore(Shell.Exec "cmd")
)
or, if you need to work with the error code further:
Target "UpdateTools" (fun _ ->
let errorCode = Shell.Exec "cmd"
//do something with the error code
()
)
Hope it is a bit clearer now.

No tail recursive code in a try catch block?

I am reading the Erlang lesson at http://learnyousomeerlang.com/errors-and-exceptions
I don't understand this part :
The Expression in between try and of is said to be protected. This means that any kind of exception happening within that call will be caught.
And
the protected part of an exception can't be tail recursive.
[...]
By putting your recursive calls between the of and catch, you are not in a protected part and you will benefit from Last Call Optimisation.
So we can't put recursive calls in the part where the exceptions are catched ? What's the point of the try catch block then ?
And below in the page we have an example with a tail recursive function in the protected section ...
has_value(Val, Tree) ->
try has_value1(Val, Tree) of
false -> false
catch
true -> true
end.
has_value1(_, {node, 'nil'}) ->
false;
has_value1(Val, {node, {_, Val, _, _}}) ->
throw(true);
has_value1(Val, {node, {_, _, Left, Right}}) ->
has_value1(Val, Left),
has_value1(Val, Right).
Does he mean that we need to use a function to wrap tail recursive code into a function when we are in the protected part of a try catch ?
So we can't put recursive calls in the part where the exceptions are
catched ? What's the point of the try catch block then ?
A function cannot recursively call itself inside of a try; or rather, tail optimization will not happen if it does. When you use try, you have to be able to jump back to the catch block at any point down the call stack. What that means is that there has to be a call stack. If tail call optimization is used, there are no function calls because they're just loops now. There's nothing to jump back to. Thus recursion inside of a try block must truly recurse.
The point is the same as exceptions in most languages. The fact that you cannot directly recurse is a bit of an annoyance, but certainly does not remove the utility of exception handling, because:
Does he mean that we need to use a function to wrap tail recursive
code into a function when we are in the protected part of a try catch
?
Yes. All it takes is one extra function and you can use try just fine, and still gain the benefits of TCO. Example:
% No TCO
func() ->
try
func()
catch _ ->
ok
end.
% TCO
func() ->
try
helper()
catch _ ->
ok
end.
helper() -> helper().
I'm not sure if there's an easy way to determine if you're accidentally recursing when you expect TCO to happen. You probably just have to be vigilant when using try.
If you want to have tail-call to be optimized, that call must be outside of try-catching clause. You can use construction
your_fun(...) ->
...
try ... of <--- make notice of `of`
... ->
some_call(...)
catch
...
end.
or just make that call after try clause.
In your code that call has_value1(Val, Right). is optimized because it's the last call in the function. It doesn't matter if it is called inside try block in this case. And exception is used only to provide early exit from this function and simple handling of the result.
It could be rewritten without exceptions but using manual stack handling:
has_value(Val, Tree) ->
has_value(Val, [Tree]).
has_value1(_, []) ->
false;
has_value1(Val, [{node, 'nil'} | Stack]) ->
has_value1(Val, Stack);
has_value1(Val, [{node, {_, Val, _, _}} | _]) ->
true;
has_value1(Val, [{node, {_, _, Left, Right}} | Stack]) ->
has_value1(Val, [Left, Right | Stack]).

Resources