Why is `;;` giving me a syntax error in utop? - ocaml

I'm working on a short project to convert small programs from python to java and visa versa.
I created the following code, and tested it in utop.
let c =
let x = "for (int i = 0; i<10; i++)"
and y = "for i in range(0,10):"
in function
| x -> y
| y -> x
| _ -> "Oh no!!";;
For some reason, x & y are both considered unbound, yet at the same time any parameter seems to match to x.
What order does everything need to be written in to make this work?

Simply to follow up with your answer.
In pattern-matching, matching to a variable doesn't necessarily seem to match to its value.
This is the very reason why it's called pattern-matching and not value-matching.
As the name implies, pattern-matching is used to match things against patterns, not values. In the code you show in the question, you are not actually comparing anything to x or y, you are defining patterns named x and y that can match anything. See the example below:
match 2 with
| x -> "Hey, I matched!"
| _ -> "Oh, I didn't match.";;
- : string = "Hey, I matched!"
Note that this works even if x was previously defined. In the match
case, the x from the pattern is actually shadowing the other one.
let x = 42 in
match 1337 with
| x -> Printf.printf "Matched %d\n!" x
| _ -> ();;
Matched 1337!
- : unit = ()
On the other hand, the pattern i when i = x is actually matching against the value of the outer variable x, which is why the code in your self-answer works. But this is not what patterns are for anyway.
What you're actually trying to do is not a pattern-matching, it is a simple conditional statement.
let c argument =
let x = "for (int i = 0; i<10; i++)" in
let y = "for i in range(0,10):" in
if argument = x then y
else if argument = y then x
else "Oh no!";;
val c : string -> string = <fun>
And here it is in action:
c "for (int i = 0; i<10; i++)";;
- : string = "for i in range(0,10):"
c "for i in range(0,10):";;
- : string = "for (int i = 0; i<10; i++)"
c "whatever";;
- : string = "Oh no!"
Also, don't use and unless you're defining mutually recursive values.

So I'm not fully understanding WHY it works this way, but I at least understand how it works.
My issue was that, in pattern-matching, matching to a variable doesn't necessarily seem to match to its value.
In short, I should be typing
function
| i when i = x -> y
| i when i = y -> x
| _ -> "Oh no!!";;
If anyone can shed some more light on what differentiates "x -> y" from I when I = x -> y, I am still curious about that.
Otherwise, thanks #ghilesZ for sending me the links I needed to figure this one out! And thanks #BahmanMovaqar for helping me understand the priority of statements a bit better.

Related

Why is function pattern matching not working, but explicit pattern matching is?

I wrote a function that take a number, and returns the negative version of that number. If the passed number is negative, it will simply return the number. make_negative :: int -> int.
My first implementation was as follows:
let make_negative x =
match x with
| 0 -> 0
| y when y < 0 -> y
| y when y > 0 -> -y
When I see this pattern, I like to think that I can replace it with the following:
let make_negative_two =
| 0 -> 0
| x when x < 0 -> x
| x when x > 0 -> -x;;
However, I see the following error: syntax error: expecting expr.
I'm not at all familiar with OCaml, in fact your post is the first I've heard of it, so my answer may be a bit naive.
But looking at your second solution, and cross referencing the "learn" documentation, something stood out.
The second solution, the one causing the syntax error, seems to be malformed, as in it is an incomplete expression. I'm not familiar with the language terminology of OCaml, but the following does pass, from a syntax checker I found online.
let make_negative_two = function
| 0 -> 0
| x when x < 0 -> x
| x when x > 0 -> -x;;
If that works, great!
To my mind the "function" keyword, completes the expression.
I referenced https://www2.lib.uchicago.edu/keith/ocaml-class/pattern-matching.html, https://ocaml.org/problems and https://try.ocamlpro.com to compose this response
Besides the syntax error, it's a rather common mistake to think branching should be done with a match (or any equivalent). That usage is only for if expressions / statements. So the proper way to write your function would be
let make_negative_three x =
if x < 0 then x else -x
Pattern matching should be reserved for deconstruction.
Also note (even though it's not directly related to the problem) that the cons function, and the typing notation in OCaml and in Haskell are inverted. That is, you would note make_negative_three : int -> int, not make_negative_three :: int -> int, which would mean in OCaml what the first version would mean in Haskell.

How to get the value of a type

I am trying to get the value of a type in my code. There is a x which is a stmt and the value is ("x" 1).
I want to get that "x" and use it as a key to find a value in a hashtable.
What I am asking is how to extract the "x".
type variable = string
type expr = int
type arrayref = variable * expr
type stmt = Dim of arrayref
let x = Dim("x",1);;
let aa (sbc:stmt) = match sbc with
|Dim a -> None;;
I should replace None to some codes, but no idea how to do that.
I'm not completely sure, but I think you're asking how to access a component of a compound value. For tuples and variants, the way to do this is with pattern matching. So you have that right. You just need to make your pattern a little deeper. To get the "x" from your value x you would do something like this:
let extracted_value =
match x with
| Dim (k, _) -> k
in
. . .
Since there is only one constructor in your stmt type (at least right now), you can do this without a match as follows:
let Dim (extracted_value, _) = x in
. . .
This works because there is a single pattern that is exhaustive. For types with more constructors you need to use match to handle all the possibilities.
If this isn't what you're asking, maybe try asking again in a different way.
Update
To print the string you could write something like this:
let Dim (k, _) = x in print_string k

Ocaml nested functions

Can someone explain the syntax used for when you have nested functions?
For example I have a outer and an inner recursive function.
let rec func1 list = match list with
[] -> []
|(head::tail) ->
let rec func2 list2 = match list2 with
...
;;
I have spent all day trying to figure this out and I'm getting a ever tiring "Syntax error".
You don't show enough code for the error to be obvious.
Here is a working example:
# let f x =
let g y = y * 5 in
g (x + 1);;
val f : int -> int = <fun>
# f 14;;
- : int = 75
Update
Something that might help until you're used to OCaml syntax is to use lots of extra parentheses:
let rec f y x =
match x with
| h :: t -> (
let incr v = if h = y then 1 + v else v in
incr (f y t)
)
| _ -> (
0
)
It's particularly hard to nest one match inside another without doing this sort of thing. This may be your actual problem rather than nested functions.

How do i make the | sign in SML?

I want to write something like
fun factorial 0 = 1
| factorial n = n * factorial(n-1);
but I don't get the "|" sign when i want to start the new line. I get something like:
fun factorial 0 = 1
= factorial n = n * factorial(n-1);
when I start the second line of code. If I hold shift and "\" I dont get the vertical bar, I get something else.
Since you say that the second line starts with an equal sign (=), it appear that you are writing your code directly into the interpreter?
In any case you have to write the pipe your self. The pipe is part of the SML syntax, and is used to "indicate" different function clauses, whereas the semicolon has a double meaning here. Doubling as being part of the SML syntax (though not strictly needed here) and as a special indicator to the interpreter (as explained below).
Most interpreters will keep reading data from stdin until it reads a semicolon, and first then will it start to interpret what you have written.
In the case of the SML/NJ interpreter, the first line is indicated by starting with a "-" and any subsequent lines starts with a "=". Note that the "-" and "=" signs are not interpreted as part of the final program.
An example of this can be seen below
- fun foo 0 y = 0
= | foo 1 y = y
= | foo x y = x*y;
val foo = fn : int -> int -> int
Here the last line is the output from the interpreter, when it reads the semicolon.
However we could also have declared two functions before writing the semicolon
- fun foo 0 y = 0
= | foo 1 y = y
= | foo x y = x * y
= fun fact 0 = 1
= | fact n = n * fact (n-1);
val foo = fn : int -> int -> int
val fact = fn : int -> int
Regarding the pipe, it depends on your keyboard layout, whether or not you will get it by typing shift+"\". However since your post contains multiple pipes, I suppose you already know how to write one.

What's the difference between "let ()=" and "let _=" ;

let () = Random.self_init();;
let _ = Random.self_init ();;
│- : unit = ()
It seems "let ()" returns nothing ?
Sincerely!
let is the keyword used to define new variables, like in the following construct:
let pattern = expr
For instance
let a = 2
assigns the value 2 to the name a. (Note this is not a way to assign a value to an already existing variable, but this is another topic).
But the pattern to the left of the = sign can be more than just a name. For instance
let (a,b) = (42,"foo")
defines both a and b, to be respectively 42 and "foo".
Of course, the types on both sides must match.
Which is the case here: both sides are of type int * string.
The expressions to the right of the = sign can also be elaborated, for instance
let foo =
let temp = String.make 10 'a' in
temp.[2] <- 'b';
temp
defines foo as the string "aabaaaaaaa". (As a side note, it also ensures that temp is local to this code snippet).
Now, let's use both: on the left, a pattern matching values of type unit, and on the right, an expression of type unit:
let () = Printf.printf "Hello world!\n"
Which explains the let () = construct.
Now, about the let _, one simply needs to know that _ can be used in a pattern as a wildcard: it matches values of any type and does not bind any name. For instance
let (a,_) = (42,"foo")
defines a as 42, and discards the value "foo". _ means "I know there is something here and I explicitly say I will not use it, so I don't name it". Here _ was used to match values of type string, but it can match value of any type, like int * string:
let _ = (42,"foo")
which does not define any variable and is not very useful. Such constructs are useful when the right hand side has side effects, like this:
let _ = Printf.printf "Hello world!\n"
which explains the second part of the question.
Practical purposes
Both are used and it's rather a matter of taste whether to use one or the other.
let () = is slightly safer as it has the compiler check that the right hand side is of type unit.
A value of any other type than unit is often a bug.
let _ = is slightly shorter (I've seen this argument). (Note that with an editor that automatically closes parenthesizes, the number of keystrokes is the same ;-)
I'm not an OCaml expert, although let me share something :)
The let in OCaml can represent two things:
The way you can assign variables;
The way you can declare functions or assign functions to names;
Using examples, you can see clearly how it works:
Assigning variables:
# let ten = 10;;
val ten : int = 10
# let hello_world_string = "Hello World";;
val hello_world_string : string = "Hello World"
Declaring functions:
# let sum a b = a+b;;
val sum : int -> int -> int = <fun>
# sum 2 3;;
- : int = 5
So, answering the question the difference between let ()= and let _= is:
At first example, you are declaring a function that doesn't have name, parameters nor instructions that should output an unit. The second example, you aren't assigning to _, that is OCaml's wildcard, any value.
As we can see below, we can define a function, that will be executed immediatly because we won't be able to call it anymore:
# let () = print_string "Hello";;
Hello
Or assign to OCaml's wildcard a type and value, or a function:
# let _ = 10;;
- : int = 10
# let _ = print_string "Maybe I answered your question :) ";;
Maybe I answered your question :) - : unit = ()