I have the following Erlang code and it is giving the warning as follows, when i try to compile it, but that make sense. function need two arguments, but i need to patten match "everything else" rather x, y or z.
-module(crop).
-export([fall_velocity/2]).
fall_velocity(P, D) when D >= 0 ->
case P of
x -> math:sqrt(2 * 9.8 * D);
y -> math:sqrt(2 * 1.6 * D);
z -> math:sqrt(2 * 3.71 * D);
(_)-> io:format("no match:~p~n")
end.
crop.erl:9: Warning: wrong number of arguments in format call.
I was trying an anonymous variable after io:format, but still it is not happy.
In the format you use ~p. It means -- print value. So you must specify what value to print.
last line of case must be
_ -> io:format("no match ~p~n",[P])
Besides, io:format returms 'ok'. So if P is not x y or z, your function will return 'ok' instead of numeric value. I would suggest to return tagged value to separate correct and error returns. Kind of
fall_velocity(P, D) when D >= 0 ->
case P of
x -> {ok,math:sqrt(2 * 9.8 * D)};
y -> {ok,math:sqrt(2 * 1.6 * D)};
z -> {ok,math:sqrt(2 * 3.71 * D)};
Otherwise-> io:format("no match:~p~n",[Otherwise]),
{error, "coordinate is not x y or z"}
end.
To make the comments to the other answer explicit, this is how I would write that function:
-module(crop).
-export([fall_velocity/2]).
fall_velocity(P, D) when D >= 0 ->
case P of
x -> math:sqrt(2 * 9.8 * D);
y -> math:sqrt(2 * 1.6 * D);
z -> math:sqrt(2 * 3.71 * D)
end.
That is, don't handle the incorrect argument in your case expression. If someone passes foo as an argument, you'll get the error {case_clause, foo} along with a stacktrace that points to this function and its caller. This also means that this function cannot leak incorrect values into the rest of the code as a result of being called with incorrect arguments.
Returning {ok, Result} | {error, Error} as in the other answer is equally valid. You'll need to choose the variant that fits your case best.
Related
I have a doubt, I have to do a tail recursion for this pow function:
pow(_, 0) -> 1;
pow(N, X) when X > 0 -> N * pow(N, X - 1).
I've read about it, but I do not totally get it, Can somebody explain me how to this function in tail recursion?
Basically in a tail recursion you need a another parameter that act as an accumulator.
%% So the first step is to convert the pow function to the pow_tail function, and initialize the accumulator to the default value.
pow(N, X) -> pow_tail(N, X, 1);
%% Defined the base case for the pow_tail, to return the accumulator
pow_tail(_, 0, ACC) -> ACC;
%% Write the pow_tail function and store the result in the accumulator
pow_tail(N, X, ACC) when X > 0 -> pow_tail(N, X-1, ACC * N);
Hope this gives you an idea how it can be done.
I would like to know if it possible to apply a try catch expression on this function:
add(X, Y) ->
X + Y.
Here the user can provide a string instead of an integer.
Another example:
myfunction(X, Y) ->
case X == Y of
true -> X + Y;
false -> X * Y
end.
I just gave those example to know if it's possible or no and how?
Yes, you can certainly use try-catch in those functions. Here what it would look like:
add(X,Y) ->
try X + Y of
Z ->
Z
catch
error:badarith ->
badargs
end.
If your concerned about values of other types being passed in, a better solution would be to add some guards to the function instead:
add(X,Y) when is_number(X), is_number(Y) ->
X + Y.
This ensures that if the function body (X + Y) is only evaluated with numbers. If something other than a number is passed as either of these arguments the process will crash with a "no function clause matching" error. This is the Erlang way of ensuring the types are correct. While Erlang is dynamically typed, but you should generally know ahead of time if the values you have are suitable for the operation you are about to perform. That said, there are times you might not know the types if the variables you have, and in such cases wrapping the call in a case statement handles incorrect types:
case {X, Y} ->
{X, Y} when is_number(X), is_number(Y) ->
% safe to call add/2
add(X, Y);
_ ->
% values aren't both numbers, so we can't add them
nocanadd
end
The second function in your question myfunction/2 really should use guards too. Like this:
myfunction(X,Y) when is_number(X), is_number(Y) ->
case X == Y of
true -> X + Y;
false -> X * Y
end.
I have the following code snippet:
let add n x = x + n
let times n x = x * n
let addTimes = add 5 >> times 5
addTimes 4
and this works without any problem. But when I change like this
let add n x = x + n
let times n x = x * n
let addTimes = add >> times
addTimes 4
I've got the compiling error
error FS0071: Type constraint mismatch when applying the default type '(int -> int)' for a type inference variable. Expecting a type supporting the operator '*' but given a function type. You may be missing an argument to a function. Consider adding further type constraints
Why?
The signature of (>>) is ('T1 -> 'T2) -> ('T2 -> 'T3) -> 'T1 -> 'T3. I.e., it composes two unary functions ā you are attempting to supply two binary functions, which is valid in general (though arguably not useful, or at the least unclear), but not for your function types:
Given that (f >> g) x is equivalent to g(f(x)), what would the expected outcome be when f is binary? In your case, x (int) is partially-applied to add (int -> int -> int), and that partial application ((int -> int)) is passed to times (also int -> int -> int), which obviously expects an int as its first parameter rather than the function type (int -> int).
I'm new to the language and trying to figure out the formatting for a simple function that returns the roots of a quadratic equation.
discriminant(A,B,C) ->
B * B - 4 * A * C.
get_roots(A,B,C) when A == 0 -> error;
get_roots(A,B,C) when discriminant(A,B,C) == 0 -> [(-B/(2*A))];
get_roots(A,B,C) when discriminant(A,B,C) > 0 ->
D = discriminant(A,B,C);
[((-1 * B + math:sqrt(D)) / 2 * A), ((-1 * B - math:sqrt(D)) / 2 * A)];
get_roots(A,B,C) when discriminant(A,B,C) < 0 -> [].
What is the syntactical mistake that I've made? The error that I get when I enter "c(ps04)" in the shell, where ps04.erl is the file in which I wrote my function, is:
ps04.erl:15: syntax error before: '['
ps04.erl:23: Warning: variable 'Head' is unused %for a different function defined later
error
You cannot use a function in guard, so get_roots(A,B,C) when discriminant(A,B,C) == 0 is forbidden.
AS mention by #Amon there is a semicolon that should be replaced by a comma. I would write the function like this:
get_roots(0,0,_) -> [];
get_roots(0,B,C) -> [-C/B];
get_roots(A,B,C) -> get_roots(A,B,C,A*A-4*B*C).
get_roots(A,B,C,0) -> [-B/(2*A)];
get_roots(A,B,C,D) when D > 0 ->
RD = math:sqrt(D),
[(-B+RD)/(2*A),(-B-RD)/(2*A)];
get_roots(_,_,_,_) -> [].
You should replace the semicolon in D = discriminant(A,B,C); with a comma:
D = discriminant(A,B,C),.
By having a semicolon, you're ending this specific get_roots/3 function clause, which is not what you want (you have an additional clause below it obviously).
On a side note, I've noticed from two of your other questions that you have never accepted an answer. If someone has answered your question and it is a valid solution, click the checkmark next to that answer.
I am currently experimenting with F#. The articles found on the internet are helpful, but as a C# programmer, I sometimes run into situations where I thought my solution would help, but it did not or just partially helped.
So my lack of knowledge of F# (and most likely, how the compiler works) is probably the reason why I am totally flabbergasted sometimes.
For example, I wrote a C# program to determine perfect numbers. It uses the known form of Euclids proof, that a perfect number can be formed from a Mersenne Prime 2pā1(2pā1) (where 2p-1 is a prime, and p is denoted as the power of).
Since the help of F# states that '**' can be used to calculate a power, but uses floating points, I tried to create a simple function with a bitshift operator (<<<) (note that I've edit this code for pointing out the need):
let PowBitShift (y:int32) = 1 <<< y;;
However, when running a test, and looking for performance improvements, I also tried a form which I remember from using Miranda (a functional programming language also), which uses recursion and a pattern matcher to calculate the power. The main benefit is that I can use the variable y as a 64-bit Integer, which is not possible with the standard bitshift operator.
let rec Pow (x : int64) (y : int64) =
match y with
| 0L -> 1L
| y -> x * Pow x (y - 1L);;
It turns out that this function is actually faster, but I cannot (yet) understand the reason why. Perhaps it is a less intellectual question, but I am still curious.
The seconds question then would be, that when calculating perfect numbers, you run into the fact that the int64 cannot display the big numbers crossing after finding the 9th perfectnumber (which is formed from the power of 31). I am trying to find out if you can use the BigInteger object (or bigint type) then, but here my knowledge of F# is blocking me a bit. Is it possible to create a powerfunction which accepts both arguments to be bigints?
I currently have this:
let rec PowBigInt (x : bigint) (y : bigint) =
match y with
| bigint.Zero -> 1I
| y -> x * Pow x (y - 1I);;
But it throws an error that bigint.Zero is not defined. So I am doing something wrong there as well. 0I is not accepted as a replacement, since it gives this error:
Non-primitive numeric literal constants cannot be used in pattern matches because they
can be mapped to multiple different types through the use of a NumericLiteral module.
Consider using replacing with a variable, and use 'when <variable> = <constant>' at the
end of the match clause.
But a pattern matcher cannot use a 'when' statement. Is there another solution to do this?
Thanks in advance, and please forgive my long post. I am only trying to express my 'challenges' as clear as I can.
I failed to understand why you need y to be an int64 or a bigint. According to this link, the biggest known Mersenne number is the one with p = 43112609, where p is indeed inside the range of int.
Having y as an integer, you can use the standard operator pown : ^T -> int -> ^T instead because:
let Pow (x : int64) y = pown x y
let PowBigInt (x: bigint) y = pown x y
Regarding your question of pattern matching bigint, the error message indicates quite clearly that you can use pattern matching via when guards:
let rec PowBigInt x y =
match y with
| _ when y = 0I -> 1I
| _ -> x * PowBigInt x (y - 1I)
I think the easiest way to define PowBigInt is to use if instead of pattern matching:
let rec PowBigInt (x : bigint) (y : bigint) =
if y = 0I then 1I
else x * PowBigInt x (y - 1I)
The problem is that bigint.Zero is a static property that returns the value, but patterns can only contain (constant) literals or F# active patterns. They can't directly contain property (or other) calls. However, you can write additional constraints in where clause if you still prefer match:
let rec PowBigInt (x : bigint) (y : bigint) =
match y with
| y when y = bigint.Zero -> 1I
| y -> x * PowBigInt x (y - 1I)
As a side-note, you can probably make the function more efficent using tail-recursion (the idea is that if a function makes recursive call as the last thing, then it can be compiled more efficiently):
let PowBigInt (x : bigint) (y : bigint) =
// Recursive helper function that stores the result calculated so far
// in 'acc' and recursively loops until 'y = 0I'
let rec PowBigIntHelper (y : bigint) (acc : bigint) =
if y = 0I then acc
else PowBigIntHelper (y - 1I) (x * acc)
// Start with the given value of 'y' and '1I' as the result so far
PowBigIntHelper y 1I
Regarding the PowBitShift function - I'm not sure why it is slower, but it definitely doesn't do what you need. Using bit shifting to implement power only works when the base is 2.
You don't need to create the Pow function.
The (**) operator has an overload for bigint -> int -> bigint.
Only the second parameter should be an integer, but I don't think that's a problem for your case.
Just try
bigint 10 ** 32 ;;
val it : System.Numerics.BigInteger =
100000000000000000000000000000000 {IsEven = true;
IsOne = false;
IsPowerOfTwo = false;
IsZero = false;
Sign = 1;}
Another option is to inline your function so it works with all numeric types (that support the required operators: (*), (-), get_One, and get_Zero).
let rec inline PowBigInt (x:^a) (y:^a) : ^a =
let zero = LanguagePrimitives.GenericZero
let one = LanguagePrimitives.GenericOne
if y = zero then one
else x * PowBigInt x (y - one)
let x = PowBigInt 10 32 //int
let y = PowBigInt 10I 32I //bigint
let z = PowBigInt 10.0 32.0 //float
I'd probably recommend making it tail-recursive, as Tomas suggested.