As practice, I want to make a function that returns the first index of a character in a string. The function takes two arguments, the string and the character to get the index of. I iterate over the string to match against the provided character. I'm printing the evaluation of each iteration for testing but it returns false even when they should be equal.
def index_of?(obj, el)
unless obj.size == 0
num = 0
while num < obj.size
puts "#{obj[num]} == #{el} : #{obj[num] == el}"
num += 1
end
end
end
str = "hello"
index_of?(str, "h")
This prints:
h == h : false
e == h : false
l == h : false
l == h : false
o == h : false
Because obj[num] returns a Char, not a String.
Doing index_of?(str, 'h') will print:
h == h : true
e == h : false
l == h : false
l == h : false
o == h : false
Related
I got some issue with my code I don't understand. Why did I get this error: This expression has type bool but an expression was expected of type unit. Here is the code
let well_formed (_dimension : int) (_initial1 : _ list)
(_initial2 : _ list) : bool =
if List.length _initial1 + List.length _initial2 != 4 * _dimension then false
else if List.length _initial1 != List.length _initial2 then false
else
let c = 0 in
for i = 1 to _dimension do
let liste =
List.filter (fun x -> x == i) _initial1
# List.filter (fun x -> x == i) _initial2
in
if List.length liste == 4 then c = c + 1 else c = c
done;
if c == _dimension then true else false
I reformated your code, actually for loop have no impact on your code.
let well_formed dimension initial1 initial2 =
let ll1 = List.length initial1 in
let ll2 = List.length initial2 in
let total_list_length = ll1 + ll2 in
if total_list_length != (4 * dimension) then false else
if ll1 != ll2 then false else
let c = 0 in
(* this code do nothing : what is expected ?
for i = 1 to dimension do
let liste = (List.filter(fun x -> x == i) initial1 )#(List.filter(fun x->x == i) initial2) in
if ( List.length liste ) == 4 then c = c+1 else c = c
done;
*)
if c == dimension then true else false
You need to learn imperative features of ocaml if you want to write code this way.
For example c = c + 1 return false
if you want to increment a variable you need to create a ref variable.
OCaml is not C/Python/Javascript, in particular
x = x + 1
means the same as
x == x + 1
in C or Python, i.e., it is a comparison operator. The == operator is the physical comparison (the same as === in Javascript).
Also, integers in OCaml are immutable, so if you want to have a mutable number you need to wrap it in a reference and use := for assignment, e.g.,
let x = ref 0 in
for i = 0 to 5 do
x := !x + 2
done
This question already has answers here:
Parse error on input 'if' when trying to use a condition inside a do block
(3 answers)
Closed 3 years ago.
I'm trying to make a very simple snake-like game where, if you try to go to a x,y coordinate you have already visited, you lose the game.
This is code that's working so far (you can move player 1 with arrowkeys and player 2 with wasd):
import UI.NCurses
main :: IO ()
main = runCurses $ do
w <- defaultWindow
updateWindow w $ do
drawBorder Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
render
loop w [] 1 1 0 0 10 10 0 0
loop :: Window -> [(Integer, Integer)] -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Curses ()
loop w list p1x p1y p1oldDx p1oldDy p2x p2y p2oldDx p2oldDy = do
e <- getEvent w (Just 100)
let coordList = updateXY e p1oldDx p1oldDy p2oldDx p2oldDy
let p1dX = coordList !! 0
let p1dY = coordList !! 1
let p2dX = coordList !! 2
let p2dY = coordList !! 3
updateWindow w $ do
moveCursor (p1y+p1dY) (p1x+p1dX)
drawString ("#")
moveCursor (p2y+p2dY) (p2x+p2dX)
drawString ("#")
render
let updatedList = list ++ [(p1y+p1dY, p1x+p1dX)] ++ [(p2y+p2dY, p2x+p2dX)]
loop w updatedList (p1x+p1dX) (p1y+p1dY) p1dX p1dY (p2x+p2dX) (p2y+p2dY) p2dX p2dY
updateXY :: Maybe Event -> Integer -> Integer -> Integer -> Integer -> [Integer]
updateXY e p1oldX p1oldY p2oldX p2oldY
| e == Just (EventSpecialKey KeyLeftArrow) = [-1, 0, p2oldX, p2oldY]
| e == Just (EventSpecialKey KeyRightArrow) = [1, 0, p2oldX, p2oldY]
| e == Just (EventSpecialKey KeyDownArrow) = [0, 1, p2oldX, p2oldY]
| e == Just (EventSpecialKey KeyUpArrow) = [0, -1, p2oldX, p2oldY]
| e == Just (EventCharacter 'a') = [p1oldX, p1oldY, -1, 0]
| e == Just (EventCharacter 'd') = [p1oldX, p1oldY, 1, 0]
| e == Just (EventCharacter 's') = [p1oldX, p1oldY, 0, 1]
| e == Just (EventCharacter 'w') = [p1oldX, p1oldY, 0, -1]
| p1oldX /= 0 = [p1oldX, 0, p2oldX, p2oldY]
| p1oldY /= 0 = [0, p1oldY, p2oldX, p2oldY]
| p2oldX /= 0 = [p1oldX, p1oldY, p2oldX, 0]
| p2oldY /= 0 = [p1oldX, p1oldY, 0, p2oldY]
| otherwise = [1, 0, 1, 0] -- Starts moving in x-direction. Change to (0,0) for stand-still
So as you move, "#" characters are put down. The above code does nothing if you go to a coordinate which already has a "#" on it, so I tried changing the loop function by adding this just before the let updatedList...:
if length (filter (==(p1x, p1y)) list) > 0 then gameOver w "player one lost"
if length (filter (==(p2x, p2y)) list) > 0 then gameOver w "player two lost"
And adding a temporary gameOver function:
gameOver w player =
updateWindow w $ do
moveCursor (10) (10)
drawString (player)
render
But when I try to load this file in GHCI I get the following error message:
parse error on input 'if'
ifs need elses. Period. You can use the when function for when you need the imperative style "if this, then do that, else do nothing," but there is no built-in syntax:
import Control.Monad
when (length (filter (==(p1x, p1y)) list) > 0) $ gameOver w "player one lost"
when (length (filter (==(p2x, p2y)) list) > 0) $ gameOver w "player two lost"
The definition of when is
when cond action = if cond then action else pure ()
In Haskell, if expressions must have both then and else clauses.
Without the else, you get the error.
Both the consequent and the alternative clause must have the same type.
I am new to SML.
How do I use the AND operator inside IF statements?
Here is my code:
val y = 1;
val x = 2;
if (x = 1 AND y = 2) then print ("YES ") else print("NO ");
My error is:
stdIn:66.9-67.3 Error: unbound variable or constructor: AND
stdIn:66.3-67.9 Error: operator is not a function [literal]
operator: int
in expression:
1
stdIn:66.3-67.9 Error: operator and operand don't agree [literal]
operator domain: bool * bool
operand: bool * int
in expression:
x = (1 ) y = 2
Thank you
There is no AND operator in SML (unless you define one yourself). There is an and keyword, but you can't use it inside if statements (or generally as a part of any expression) because it's not an operator. It's used in combination with fun to define mutually recursive functions.
You're probably looking for the andalso operator, which takes two boolean operands and returns true if and only if both operands are true.
May I disagree with Vishal's comment?
*-true andalso true ;
val it = false : bool
-true andalso false ;
val it = false : bool*
I think (and so does the REPL) that
true andalso true ;
evaluates to true, not false
here is an example which will clear the usage of andalso
-true andalso true ;
val it = false : bool
- true andalso false ;
val it = false : bool
one and one in digital gates is always 1; therefore
in the above case true andalso true "must necessarily evaluate to true , not false; am'i correct ?
also 1 and 0 can't never be 1;
1 or 0 can be 1;
I'm a complete newbie in OCaml and trying to create a simple console program.
(*let k = read_int()
let l = read_int()
let m = read_int()
let n = read_int()
let d = read_int()*)
let k = 5
let l = 2
let m = 3
let n = 4
let d = 42
let rec total: int -> int -> int = fun i acc ->
if i > d then
acc
else
if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then
total (i + 1) (acc + 1)
else
total (i + 1) acc;
print_int (total 1 0)
But if I try to compile it, it fails:
PS C:\Users\user> ocamlc -g .\a148.ml
File ".\a148.ml", line 14, characters 2-180:
Warning S: this expression should have type unit.
File ".\a148.ml", line 22, characters 0-21:
Error: This expression has type unit but is here used with type int
So, looks like if expression cannot return value here (why?). I've added let binding
let k = 5
let l = 2
let m = 3
let n = 4
let d = 42
let rec total: int -> int -> int = fun i acc ->
let x' = if i > d then
acc
else
if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then
total (i + 1) (acc + 1)
else
total (i + 1) acc;
x'
print_int (total 1 0)
and it works, but raises another error:
File ".\a148.ml", line 23, characters 0-0:
Error: Syntax error
Line 23 is the next to print_int statement and empty, so it seems like compiler wants something else from me, but I don't know what.
UPD: ok, the working code:
let k = 5 in
let l = 2 in
let m = 3 in
let n = 4 in
let d = 42 in
let rec total i acc =
if i > d then
acc
else
if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then
total (i + 1) (acc + 1)
else
total (i + 1) acc
in let x = total 1 0 in
print_int x;
The problem is the misuse of semicolon (;).
Semicolon intends to be the sequence composition of two expressions. S1 ; S2 means that the compiler expects S1 to be unit type, computes S1 and S2 in that order and returns the result of S2.
Here you mistakenly use ;, so OCaml expects the second if...then...else to return unit and wants you to provide one more expression. Removing ; and adding necessary in(s) should make the function compile:
let k = 5 in
let l = 2 in
let m = 3 in
let n = 4 in
let d = 42 in
let rec total: int -> int -> int = fun i acc ->
if i > d then
acc
else
if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then
total (i + 1) (acc + 1)
else
total (i + 1) acc
Regarding your second function, you should replace ; by in to indicate that x' is used to compute the return value.
BTW, your total function looks weird since you use lambda expression in the function body. Explicit declaration is more readable:
let rec total i acc =
if i > d then
acc
else if i mod k = 0 || i mod l = 0 || i mod m = 0 || i mod n = 0 then
total (i + 1) (acc + 1)
else
total (i + 1) acc
I have also changed reference equality (==) to structural equality (=) though there is no difference among them in integer.
It seems to be an equivalency comparison for some types, but not strings.
# 3 != 3;;
- : bool = false
# 3 != 2;;
- : bool = true
This is as expected.
# "odp" = "odp";;
- : bool = true
# "odp" != "odp";;
- : bool = true
# "odp" <> "odp";;
- : bool = false
Why does "odp" != "odp" evaluate to true? What is it actually doing? Shouldn't it generate a type error?
you have experienced the difference between structural and physical equality.
<> is to = (structural equality) as != is to == (physical equality)
"odg" = "odg" (* true *)
"odg" == "odg" (* false *)
is false because each is instantiated in different memory locations, doing:
let v = "odg"
v == v (* true *)
v = v (* true *)
Most of the time you'll want to use = and <>.
edit about when structural and physical equality are equivalent:
You can use the what_is_it function and find out all the types that would be equal both structurally and physically. As mentioned in the comments below, and in the linked article, characters, integers, unit, empty list, and some instances of variant types will have this property.
The opposite for != operator is == operator, not the = one.
# "a" != "a" ;;
- : bool = true
# "a" == "a" ;;
- : bool = false
The == operator is a "physical equality". When you type "a" == "a", you compare two different instances of strings that happen to look alike, so the operator returns false. While having one instance makes it return true:
# let str = "a"
in str == str ;;
- : bool = true
# let str = "a"
in str != str ;;
- : bool = false
A quick explanation about == and != in OCaml in addition to all the correct answers that have already been provided:
1/ == and != expose implementation details that you really don't want to know about. Example:
# let x = Some [] ;;
val x : 'a list option = Some []
# let t = Array.create 1 x ;;
val t : '_a list option array = [|Some []|]
# x == t.(0) ;;
- : bool = true
So far, so good: x and t.(0) are physically equal because t.(0) contains a pointer to the same block that x is pointing to. This is what basic knowledge of the implementation dictates. BUT:
# let x = 1.125 ;;
val x : float = 1.125
# let t = Array.create 1 x ;;
val t : float array = [|1.125|]
# x == t.(0) ;;
- : bool = false
What you are seeing here are the results of an otherwise useful optimization involving floats.
2/ On the other hand, there is a safe way to use ==, and that is as a quick but incomplete way to check for structural equality.
If you are writing an equality function on binary trees
let equal t1 t2 =
match ...
checking t1 and t2 for physical equality is a quick way to detect that they are obviously structurally equal, without even having to recurse and read them. That is:
let equal t1 t2 =
if t1 == t2
then true
else
match ...
And if you keep in mind that in OCaml the “boolean or” operator is “lazy”,
let equal t1 t1 =
(t1 == t2) ||
match ...
They are like two "Tom"s in your class! Because:
In this case, "odp" = "odp"
because they are TWO strings with SAME VALUE!!
So they are not == because they are TWO different strings store in different (Memory) location
They are = because they have the identical string value.
One more step deeper, "odp" is anonymous variable. And two anonymous variable leads to this Two strings.
For your convenience:
# "odp" = "odp";;
- : bool = true
# "odp" != "odp";;
- : bool = true
# "odp" <> "odp";;
- : bool = false
ints are the only type where physical and structural equality are the same, because ints are the only type that is unboxed