This question already has answers here:
Rewrite variable in Erlang
(3 answers)
Closed 6 years ago.
I has code that is looking for max palindrome, alias N = reverse(N). The code isn't complete yet. But help me please find out reason of exception.
find_palindrome(List1, List2, Increment, IfPalindrome) ->
List_of_values = [X * Y || X <- List1, Y <- List2],
find_palindrome(0, 1, List_of_values, Increment, IfPalindrome).
find_palindrome(Max, N, List_of_values, Increment, IfPalindrome) ->
case IfPalindrome(lists:nth(N, List_of_values)) of
true ->
case Max < lists:nth(N, List_of_values) of
true ->
Max = lists:nth(N, List_of_values),
find_palindrome(Max, Increment(N), List_of_values, Increment, IfPalindrome);
false ->
find_palindrome(Max, Increment(N), List_of_values, Increment, IfPalindrome)
end;
false ->
find_palindrome(Max, Increment(N), List_of_values, Increment, IfPalindrome)
end.
check_palindrome(N) ->
(N) == (list_to_integer(lists:reverse(integer_to_list(N)))).
problem4() ->
find_palindrome(lists:seq(100, 999), lists:seq(100, 999), fun(X) -> X = X + 1 end, fun check_palindrome/1).
I am constantly getting exception:
** exception error: no match of right hand side value 2
in function euler4:'-problem4/0-fun-0-'/1 (euler4.erl, line 36)
in call from euler4:find_palindrome/5 (euler4.erl, line 28)
Try this in Erlang shell:
1> X = 1.
1
2> X = X + 1.
** exception error: no match of right hand side value 2
This is because in Erlang variables can only be assigned once. It's called single assignment. Once a variable is bound to a value, that variable can't be be bound to any other value. The value stored in a variable can't change. You need to create a new variable. In this particular case you could write:
3> Y = X + 1.
2
You should know that = is really a pattern matching operator, not assignment. The left-hand side can be any pattern, not just a variable. You can write e.g. 2 = 1 + 1 and this will successfully match, while 3 = 1 + 1 will give you no match of right hand side value 2. And bound variables can be used in the pattern for their values, e.g. X = 2, X = 1 + 1 will succeed.
So in Max = lists:nth(N, List_of_values), because Max is already bound (as the argument of the function), its value is used, and it ends up being 0 = lists:nth(1, List_of_values) (with values from find_palindrome(0, 1, List_of_values, Increment, IfPalindrome) which will fail unless List_of_values starts with 0.
Related
I have been trying to write a program which prints out a factorial without actually using recursion.
Here is the code
let factorial x =
let mutable n = x
while n > 0 do
let result = n*(n-1)
n <- (n-1)
result
The issue is that when I try to run the code it tells me that the expected result is a unit, whereas the input is clearly an integer, which obviously results in an error. However, I have checked all my variables and the compiler interprets them as integers, so what is the issue
There are several issues with your code here, you must keep in mind indentation in f# is very important, for you want to do your code should be:
let factorial x =
let mutable n = x
let mutable result = 1
while n > 0 do
result <- n * (n-1)
n <- (n - 1)
result
You were declaring the result variable inside the while scope and returning it outside it. Your code however is incorrect, I took the liberty of modify it, here what I did:
let factorial x =
let mutable n = x
let mutable result = 1
while n >= 1 do
result <- result * n
n <- (n - 1)
result
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.
This question already has answers here:
F# Functions vs. Values
(4 answers)
Closed 8 years ago.
Newby question f# related,
What is the difference between this definitions in f# ?
module s
let log p =
printfn "expression is %A" p
let loggedWorkflow =
let x = 42
log x
let y = 43
log y
let z = x + y
log z
z
s.loggedWorkflow
and this one
module s
let log p =
printfn "expression is %A" p
let loggedWorkflow() =
let x = 42
log x
let y = 43
log y
let z = x + y
log z
z
s.loggedWorkflow()
The first one does not call the inner log, only returns z value
Why it works this way?
Thanks :)
I take this sample from
http://fsharpforfunandprofit.com/posts/computation-expressions-intro/
let loggedWorkflow = ... is defining a value. The body is evaluated as soon as the definition is reached (typically when the module s is loaded), and the value of loggedWorkflow is remembered as the result of evaluating the body, and returned every time someone evaluates s.loggedWorkflow.
let loggedWorkflow() = ... is defining a function that takes a single argument of type unit - the only value of this type is (), also typically pronounced "unit". The body doesn't get evaluated straight away, but only when the function is actually called. Each time it is called by actually passing an argument of type unit, e.g. with s.loggedWorkflow(), the body is evaluated and the resulting value returned.
Am trying to count down from 6 to 1 in a non-recursive factorial function and getting a compiler error:
let fact x =
let mutable product = 1
for i in x..-1..1 do
product <- product * i
product
// Error on the 6 - type 'int' does not support the operator '..-'
let answer = fact 6
printfn "%i" answer
I got this idea from near the bottom here
Have changed the function to just count up and it works, but I'm interested to know why this failed. Is there a better way to count down?
Using VS2012 update 3
Have changed the function to just count up and it works, but I'm interested to know why this failed.
Your example fails because .. and - are two different operators, the compiler needs separation between those. Instead of wrapping -1 by parentheses, you could add spaces:
let fact x =
let mutable product = 1
for i in x .. -1 .. 1 do
product <- product * i
product
Is there a better way to count down?
The less well-known for .. downto .. do construct is more appropriate to use here.
let fact x =
let mutable product = 1
for i = x downto 1 do
product <- product * i
product
This works:
let fact x =
let mutable product = 1
for i in x..(-1)..1 do
product <- product * i
product
As does this (as used in the link in the question):
let fact x =
let mutable product = 1
for i in x .. -1 .. 1 do
product <- product * i
product
PS: also note that there are more functional ways to compute a factorial (bad to use mutable variables); the most obvious using recursion:
let rec fact x =
if x > 2
then x * (fact (x - 1))
else x
or a one-liner using lists:
let fact x = [2..x] |> List.reduce (*)
Try to use brackets:
...
for i in x..(-1)..1 do
...
i would like to add 1 items to a list which has only one item and add items(after using toInt to convert to integer) in a list y if number of items greater than 1 and the last items are the same
How to do?
import Data.List.Split
z = splitOn "+" "x^2+2*x^3+x^2"
y = map (splitOn "*") z
x = map head y
toInt :: [String] -> [Int]
toInt = map read
u = filter ((map length y)>1) y
Couldn't match expected type `a0 -> Bool' with actual type `Bool'
In the first argument of `filter', namely `((map length y) > 1)'
In the expression: filter ((map length y) > 1) y
In an equation for `u': u = filter ((map length y) > 1) y
Failed, modules loaded: none.
Your definition of u is obviously bad. It helps if you give type signatures, so we understand a little better what you are trying to do (even when you don't tell us in words).
You commented that you want all lists of length > 1, this is the same as getting all non-null lists after dropping the first element. So use filter, which tests each element separately (so you don't need map), and build a function that either tests a single list for length > 1 or it's sublist for null:
-- Use the O(n) length for your filter
u = filter ((> 1) . length) y
-- Or use an O(1) drop + null test
u' = filter (not . null . drop 1) y
Without using function composition (.) these functions are:
u = filter (\sublist -> length (sublist) > 1) y
u' = filter (\sublist -> not (null (drop 1 sublist))) y
The compiler is telling you that map length y > 1 is a boolean value, but filter wants a function there. I am not sure what you really want do to with y, please specify what you expect for different values of y.