Erlang How to mix try catch with if - erlang

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.)

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).

iOS RxSwift how to prevent sequence from being disposed on (throw error)?

I have a sequence made up of multiple operators. There are total of 7 places where errors can be generated during this sequence processing. I'm running into an issue where the sequence does not behave as I expected and I'm looking for an elegant solution around the problem:
let inputRelay = PublishRelay<Int>()
let outputRelay = PublishRelay<Result<Int>>()
inputRelay
.map{ /*may throw multiple errors*/}
.flatmap{ /*may throw error*/ }
.map{}
.filter{}
.map{ _ -> Result<Int> in ...}
.catchError{}
.bind(to: outputRelay)
I thought that catchError would simply catch the error, allow me to convert it to failure result, but prevent the sequence from being deallocated. However, I see that the first time an error is caught, the entire sequence is deallocated and no more events go through.
Without this behavior, I'm left with a fugly Results<> all over the place, and have to branch my sequence multiple times to direct the Result.failure(Error) to the output. There are non-recoverable errors, so retry(n) is not an option:
let firstOp = inputRelay
.map{ /*may throw multiple errors*/}
.share()
//--Handle first error results--
firstOp
.filter{/*errorResults only*/}
.bind(to: outputRelay)
let secondOp = firstOp
.flatmap{ /*may throw error*/ }
.share()
//--Handle second error results--
secondOp
.filter{/*errorResults only*/}
.bind(to: outputRelay)
secondOp
.map{}
.filter{}
.map{ _ -> Result<Int> in ...}
.catchError{}
.bind(to: outputRelay)
^ Which is very bad, because there are around 7 places where errors can be thrown and I cannot just keep branching the sequence each time.
How can RxSwift operators catch all errors and emit a failure result at the end, but NOT dispose the entire sequence on first error?
The first trick to come to mind is using materialize. This would convert every Observable<T> to Observable<Event<T>>, so an Error would just be a .next(.error(Error)) and won't cause the termination of the sequence.
in this specific case, though, another trick would be needed. Putting your entire "trigger" chain within a flatMap, as well, and materializeing that specific piece. This is needed because a materialized sequence can still complete, which would cause a termination in case of a regular chain, but would not terminate a flatMapped chain (as complete == successfully done, inside a flatMap).
inputRelay
.flatMapLatest { val in
return Observable.just(val)
.map { value -> Int in
if value == 1 { throw SomeError.randomError }
return value + value
}
.flatMap { value in
return Observable<String>.just("hey\(value)")
}
.materialize()
}
.debug("k")
.subscribe()
inputRelay.accept(1)
inputRelay.accept(2)
inputRelay.accept(3)
inputRelay.accept(4)
This will output the following for k :
k -> subscribed
k -> Event next(error(randomError))
k -> Event next(next(hey4))
k -> Event next(completed)
k -> Event next(next(hey6))
k -> Event next(completed)
k -> Event next(next(hey8))
k -> Event next(completed)
Now all you have to do is filter just the "next" events from the materialized sequence.
If you have RxSwiftExt, you can simply use the errors() and elements() operators:
stream.elements()
.debug("elements")
.subscribe()
stream.errors()
.debug("errors")
.subscribe()
This will provide the following output:
errors -> Event next(randomError)
elements -> Event next(hey4)
elements -> Event next(hey6)
elements -> Event next(hey8)
When using this strategy, don't forget adding share() after your flatMap, so many subscriptions don't cause multiple pieces of processing.
You can read more about why you should use share in this situation here: http://adamborek.com/how-to-handle-errors-in-rxswift/
Hope this helps!
Yes, it's a pain. I've thought about the idea of making a new library where the grammar doesn't require the stream to end on an error, but trying to reproduce the entire Rx ecosystem for it seems pointless.
There are reactive libraries that allow you to specify Never as the error type (meaning an error can't be emitted at all,) and in RxCocoa you can use Driver (which can't error) but you are still left with the whole Result dance. "Monads in my Monads!".
To deal with it properly, you need a set of Monad transformers. With these, you can do all the mapping/flatMapping you want and not worry about looking at the errors until the very end.

Haskell - response code of simpleHTTP method

I've written the following Haskell code to download the CSV file (daliy prices) available on yahoo finance web site . In the last part of the code, there's a case statement. I would like to know when actually "rcode" contains the "Left" value. I've mentioned three cases, but all of them refer to "Right" values. I may be wrong. I'm referring to the HTTP response codes available on the following web site.
downloadCSVFile ::String-> IO (Bool,String)
downloadCSVFile company_code=do
let a="http://ichart.finance.yahoo.com/table.csv?s=" ++ company_code
let b=simpleHTTP $ getRequest a
src <- ( b >>= getResponseBody)
rcode <- fmap rspCode <$> b
case rcode of
Right (2,_,_) -> return (True,src)
Right (4,_,_) -> return (False,"Invalid URL..")
Right (5,_,_) -> return (False, "Server Error")
https://support.google.com/webmasters/answer/40132?hl=en
The Result a type that gets threaded around is an alias for Either ConnError a.
You'll get a Left value if the HTTP client library had some actual problem when connecting to the server. If it successfully connected to the server and received a HTTP response code from the server, that will always be a Right value.
See the Network.HTTP documentation for more details.
To handle the error cases, do something like this:
case rcode of
Left err -> return (False, "Connection error: " ++ show err)
Right (2,_,_) -> return (True,src)
Right (4,_,_) -> return (False,"Invalid URL..")
Right (5,_,_) -> return (False, "Server Error")
Right code -> return (False, "Unexpected code: " ++ show code)
I also added a "catch-all" case in case you get an unexpected response from the server.

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]).

Erlang throw statement not working in a function handler

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

Resources