What's the difference between function_clause and badarg in Erlang? - exception

Sometimes I get badarg instead of function_clause but I cannot see the rule that would determine which one is going to appear.
As I understand, function_clause is thrown when no function's implementation matches given arguments. About badarg the documentation says
The argument is of wrong data type, or is otherwise badly formed.
which seems to be covered by function_clause conditions...
For instance
lists:flatten(3).
throws clause error, while the type definitely does not match.

Function clauses are parts of definition with different argument patterns/guards, as in
func({X, Y}) -> ...;
func(X) when X > 10 -> ...;
func(_) -> ...
function_clause means that none of them matched. There are similar if_clause and case_clause. For flatten with single argument there is only one clause
flatten(List) when is_list(List) ->
do_flatten(List, []).
which doesn't match 3, which is why you get function_clause.
So
Sometimes I get badarg instead of function_clause but I cannot see the rule that would determine which one is going to appear
This is basically an implementation detail which you should only care about when debugging the implementation of that function.

1> F = fun({X,L}) -> X + hd(L) end.
#Fun<erl_eval.7.91303403>
2> catch(F(5)). % 5 is not a tuple, so there is no clause in F definition which allow any evaluation
{'EXIT',{function_clause,[{erl_eval,'-inside-an-interpreted-fun-',
[5],
[]},
{erl_eval,eval_fun,6,[{file,"erl_eval.erl"},{line,829}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,437}]},
{shell,exprs,7,[{file,"shell.erl"},{line,686}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]}}
3> catch(F({5,6})). % in the tuple, 6 is not a list, it is a bad argument for erlang:hd/1
{'EXIT',{badarg,[{erlang,hd,[6],[]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,684}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,480}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,437}]},
{shell,exprs,7,[{file,"shell.erl"},{line,686}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]}}
4> catch(F({5,[a]})). % now the error is detected in the addition you get a badarith
{'EXIT',{badarith,[{erlang,'+',[5,a],[]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,684}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,437}]},
{shell,exprs,7,[{file,"shell.erl"},{line,686}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]}}
5> catch(F({5,[6]})).
11
6>

here is the Official explanation:
badarg
Bad argument. The argument is of wrong data type, or is otherwise badly formed.
function_clause
No matching function clause is found when evaluating a function call.
sometimes badarg should be coverd by function_clause
but when do math operation, for example 1/0 will throw badarg
at most cases, when a function definition with a guard will throw function_clause

Related

Maxima indexed variables assigned in evaluation of function

I'd like to use an indexed variable in a function definition (this is a MWE, in the real world I have many a[i], used as coefficients of a polynomial)
f(x):=a[0]*x $
But when I evaluate this function assigning a value to a[0], the assignment is ignored:
ev(f(z),[a[0]=99]);
> a[0]*z
In order to get the desired result I need to make an additional assignment
expr:f(z) $
ev(expr,[a[0]=99]);
> 99*z
What's happening here? Is there a way to avoid the additional step?
Thanks in advance for any clue.
I see that if you write the function as f(x) := a0*x and then ev(f(z), a0=99), you'll get the expected result 99*z. The different behavior for f(x) := a[0]*x is therefore a bug; I'll file a bug report.
In general a more predictable strategy for replacing placeholders with values is to use the subst function which substitutes values into an expression. In this case you could write:
subst (a[0] = 99, f(z));
If you have several values to substitute, you can write:
subst ([a[0] = 99, a[1] = 42, a[2] = 2*foo], myexpr);
where myexpr is an expression containing a[0], a[1], and a[2].
subst is serial (one value at a time) substitution. See also psubst which is parallel substitution (all values at once).

How does the recursive call work in this erlang function?

fun({0, M}) -> {M+1, M-2};
fun({N, M}) ->
{A, B} = fun({N-1, M+1}),
{B, A+1}.
so I am kinda unsure of what the A and B would be and how the next recursive call would be. let say 2,2
so it would be
f(2,2) -> {A,B} = fun({1,3}), {B,A+1}
f(1,3) -> {A,B} = fun({0,4}), {B,A+1}
f(0,4) -> {5,2}
but where does A and B go and do they change in each recursive call?
As a very basic explanation of "where is my variable", consider the countdown function in this example module:
-module(example).
-export([countdown/1]).
-spec countdown(non_neg_integer()) -> ok.
countdown(0) ->
io:format("Blastoff!~n");
countdown(N) when N > 0 ->
ok = io:format("Counting down in: ~w~n", [N]),
Next = N - 1,
countdown(Next).
If we hit the base case, which is 0, then we stop. The return value of the function overall is the atom ok (because that is the return value of a successful call to io:format/2).
If the input is greater than 0 then we match on the second clause, which means we assign N the sole input argument for this particular iteration. The next thing we do is make our output call. Then we assign Next to the value N - 1. Then we call the same function again (do a loop) using the value of Next in body of the the current call as the input argument.
The next iteration all the variables are totally new because this is a fresh execution context. The old N and Next no longer exist. In fact, they don't event exist on a stack anywhere because Erlang uses "tail call optimization" to maintain recursive tail calls in constant space, the same way most other languages would do an explicit for or while or do while or [insert form].
As Alexy points out, be careful about the token fun -- it is a keyword in Erlang, not a legal function name. It is the non-name of an anonymous function (also known as a lambda). In other words, unless you provide a label, the name of every anonymous function is just fun.
fun is also the keyword that is used to reference a function by label (to use as a value itself) instead of calling it. For example, countdown(10) calls the function above with an argument of 10. Referencing the function as fun countdown/1 returns the function itself as a value. That is, incidentally, why the function export declaration at the top of the module is written as -module([countdown/1]), because that is the explicit name of this function. Consider this:
1> c(example).
{ok,example}
2> example:countdown(2).
Counting down in: 2
Counting down in: 1
Blastoff!
ok
3> Countdown = fun example:countdown/1.
#Fun<example.countdown.1>
4> Countdown(2).
Counting down in: 2
Counting down in: 1
Blastoff!
ok
While I'm on the subject...
Erlang has very few keywords compared to most languages (and very little syntax, actually). Here is the list of reserved words:
after and andalso band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse receive rem try when xor
You just need to go back up:
f({1, 3}) -> {A, B} = {5, 2}, {B, A+1} -> {2, 6}
f({2, 2}) -> {A, B} = {2, 6}, {B, A+1} -> {6, 3}
(note that fun is a keyword in Erlang and that f(N,M) is not the same as f({N,M}))
and do they change in each recursive call
Yes, as you can see.

golang return multiple values issue

I was wondering why this is valid go code:
func FindUserInfo(id string) (Info, bool) {
it, present := all[id]
return it, present
}
but this isn't
func FindUserInfo(id string) (Info, bool) {
return all[id]
}
is there a way to avoid the temporary variables?
To elaborate on my comment, the Effective Go mentions that the multi-value assignment from accessing a map key is called the "comma ok" pattern.
Sometimes you need to distinguish a missing entry from a zero value. Is there an entry for "UTC" or is that the empty string because it's not in the map at all? You can discriminate with a form of multiple assignment.
var seconds int
var ok bool
seconds, ok = timeZone[tz]
For obvious reasons this is called the “comma ok” idiom. In this example, if tz is present, seconds will be set appropriately and ok will be true; if not, seconds will be set to zero and ok will be false.
Playground demonstrating this
We can see that this differs from calling a regular function where the compiler would tell you that something is wrong:
package main
import "fmt"
func multiValueReturn() (int, int) {
return 0, 0
}
func main() {
fmt.Println(multiValueReturn)
asgn1, _ := multiValueReturn()
asgn2 := multiValueReturn()
}
On the playground this will output
# command-line-arguments
/tmp/sandbox592492597/main.go:14: multiple-value multiValueReturn() in single-value context
This gives us a hint that it may be something the compiler is doing. Searching the source code for "commaOk" gives us a few places to look, including types.unpack
At the time of writing this it this the method's godoc reads:
// unpack takes a getter get and a number of operands n. If n == 1, unpack
// calls the incoming getter for the first operand. If that operand is
// invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a
// function call, or a comma-ok expression and allowCommaOk is set, the result
// is a new getter and operand count providing access to the function results,
// or comma-ok values, respectively. The third result value reports if it
// is indeed the comma-ok case. In all other cases, the incoming getter and
// operand count are returned unchanged, and the third result value is false.
//
// In other words, if there's exactly one operand that - after type-checking
// by calling get - stands for multiple operands, the resulting getter provides
// access to those operands instead.
//
// If the returned getter is called at most once for a given operand index i
// (including i == 0), that operand is guaranteed to cause only one call of
// the incoming getter with that i.
//
The key bits of this being that this method appears to determine whether or not something is actually a "comma ok" case.
Digging into that method tells us that it will check to see if the mode of the operands is indexing a map or if the mode is set to commaok (where this is defined does give us many hints on when it's used, but searching the source for assignments to commaok we can see it's used when getting a value from a channel and type assertions). Remember the bolded bit for later!
if x0.mode == mapindex || x0.mode == commaok {
// comma-ok value
if allowCommaOk {
a := [2]Type{x0.typ, Typ[UntypedBool]}
return func(x *operand, i int) {
x.mode = value
x.expr = x0.expr
x.typ = a[i]
}, 2, true
}
x0.mode = value
}
allowCommaOk is a parameter to the function. Checking out where unpack is called in that file we can see that all callers pass false as an argument. Searching the rest of the repository leads us to assignments.go in the Checker.initVars() method.
l := len(lhs)
get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())
Since it seems that we can only use the "comma ok" pattern to get two return values when doing a multi-value assignment this seems like the right place to look! In the above code the length of the left hand side is checked, and when unpack is called the allowCommaOk parameter is the result of l == 2 && !returnPos.IsValid(). The !returnPos.IsValid() is somewhat confusing here as that would mean that the position has no file or line information associated with it, but we'll just ignore that.
Further down in that method we've got:
var x operand
if commaOk {
var a [2]Type
for i := range a {
get(&x, i)
a[i] = check.initVar(lhs[i], &x, returnPos.IsValid())
}
check.recordCommaOkTypes(rhs[0], a)
return
}
So what does all of this tell us?
Since the unpack method takes an allowCommaOk parameter that's hardcoded to false everywhere except in assignment.go's Checker.initVars() method, we can probably assume that you will only ever get two values when doing an assignment and have two variables on the left-hand side.
The unpack method will determine whether or not you actually do get an ok value in return by checking if you are indexing a slice, grabbing a value from a channel, or doing a type assertion
Since you can only get the ok value when doing an assignment it looks like in your specific case you will always need to use variables
You may save a couple of key strokes by using named returns:
func FindUserInfo(id string) (i Info, ok bool) {
i, ok = all[id]
return
}
But apart from that, I don't think what you want is possible.
Simply put: the reason why your second example isn't valid Go code is because the language specification says so. ;)
Indexing a map only yields a secondary value in an assignment to two variables. Return statement is not an assignment.
An index expression on a map a of type map[K]V used in an assignment or initialization of the special form
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
yields an additional untyped boolean value. The value of ok is true if the key x is present in the map, and false otherwise.
Furthermore, indexing a map is not a "single call to a multi-valued function", which is one of the three ways to return values from a function (the second one, the other two not being relevant here):
There are three ways to return values from a function with a result type:
The return value or values may be explicitly listed in the "return" statement. Each expression must be single-valued and assignable to the corresponding element of the function's result type.
The expression list in the "return" statement may be a single call to a multi-valued function. The effect is as if each value returned from that function were assigned to a temporary variable with the type of the respective value, followed by a "return" statement listing these variables, at which point the rules of the previous case apply.
The expression list may be empty if the function's result type specifies names for its result parameters. The result parameters act as ordinary local variables and the function may assign values to them as necessary. The "return" statement returns the values of these variables.
As for your actual question: the only way to avoid temporary variables would be using non-temporary variables, but usually that would be quite unwise - and probably not much of an optimization even when safe.
So, why doesn't the language specification allow this kind of special use of map indexing (or type assertion or channel receive, both of which can also utilize the "comma ok" idiom) in return statements? That's a good question. My guess: to keep the language specification simple.
I'm no Go expert but I believe you are getting compile time error when you are trying to return the array i.e. return all[id]. The reason could be because the functions return type is specially mentioned as (Info, bool) and when you are doing return all[id] it can't map the return type of all[id] to (Info, bool).
However the solution mentioned above, the variables being returned i and ok are the same that are mentioned in the return type of the function (i Info, ok bool) and hence the compiler knows what it's returning as opposed to just doing (i Info, ok bool).
By default, maps in golang return a single value when accessing a key
https://blog.golang.org/go-maps-in-action
Hence, return all[id] won't compile for a function that expects 2 return values.

Ocaml calling function without giving right number of arguments

If I have a function in ocaml specified by:
let rec new_grammar rules nonterm =
match rules with
| (expr, rules) -> if expr = nonterm then ............
and I call it in another place by saying new_grammar rules
How does expr know if its equal to nonterm since I didn't feed in the argument for nonterm
If you apply function without giving a full number of arguments or, in OCaml parlance, when you make a partial application, then the resulting value will be a function, that will take the rest arguments, and evaluate to the expected return value.
Example, if you have function sum defined as:
let sum x y = x + y
and later you apply it partially to one argument:
let plus_2 = sum 2
then plus_2 would be an unary function of type int -> int, accepting one argument (namely y) and adding to it 2 (and argument assigned to a formal parameter x)

Scheme equality of returning value

I'm at beginning with Scheme. I'm trying to check equality of returning boolean value
(cond [(= (Test number) #t) 1])]
If my test function returns true, my main function should return 1. But I get contract violation error. Is there anybody could help me?
= is only used to compare numbers. eq? would be the correct equality procedure if you really need to check if something really is #t.
Normally any value not #f is considered a true value and if that is ok you should do this:
(cond [(Test number) 1]
[else 'else-case])
Your cond misses a default case, like the one I've added. In case your Test return #f you really need it or else the result is undefined.
A related question on SO is What is the difference between eq?, eqv?, equal?, and = in scheme?