SML: syntax error: replacing LET with RAISE - sml

I'm writing a function, that takes date in (d, m, y) format. I need to count rez value, all of these +getNthInt function calls are adding certain elements from the list.
fun firstNewMoonInt ((d, m, y) : int * int * int) : int option =
let
if m = 1 orelse m = 2 then y - 1
else y
val rez = newStyleCorrection (d, m, y) * 100000
+ getNthInt(thousandCorrection, y div 1000)
+ getNthInt (hundredCorrection, y div 100 mod 10)
+ getNthInt (decadeCorrection, y mod 100 div 10)
+ getNthInt (yearCorrection, y mod 1000)
+ getNthInt (monthCorrection, m - 1)
+ getNthInt (calendarCorrection, y mod 4)
rez - lastSmaller(rez - 100000, reductions)
in
if rez div 100000 <= 30 then SOME rez
else NONE
end
I'm getting two syntax errors:
2.3-2.6 Error: syntax error: replacing LET with RAISE
13.3 Error: syntax error: inserting LET
Since I use all keywords for the constructions: let-in-end, if-then-else. I don't understand, what is wrong with my code?

Immediately inside a let, there should be a sequence of declarations. (Declarations are things like val x = ... or fun f x = ...). But in your code, there is an if which begins an expression.
You could fix this by making a new variable which is the result of the if expression:
let
val new_y =
if m = 1 orelse m = 2 then y - 1
else y
val rez = ...
And then you will need to figure out where to use new_y in the rest of the code.
Note that there is a similar problem just a few lines further down:
rez - lastSmaller(rez - 100000, reductions)
This is an expression where there should be another declaration. You could also fix it the same way: val new_rez = rez - lastSmaller (...) and then use new_rez where appropriate below that.

Related

Can we use an assert statement inside a function in OCaml?

I wrote a simple recursive fibonacci program that works fine without an assert statement, but when I add an assert statement, even with various permutations of parentheses, spaces, and double semicolons, I keep getting a syntax error during compilation.
Working function:
let rec fib n =
if n = 1
then 1
else
n*(fib (n-1))
Not working:
let rec fib n =
assert (n>=0)
if n = 1
then 1
else
n*(fib (n-1))
Any thoughts appreciated.
Thanks.
You have two expressions: assert (n >= 0) and if ... then ... else .... If you want the two expressions to be evaluated in sequence (which you do), you need to separate them with a semicolon:
let rec fib n =
assert (n >= 0);
if n = 1 then 1
else n * fib (n - 1);;
val fib : int -> int = <fun>
# fib 3;;
- : int = 6
# fib (-3);;
Exception: Assert_failure ("//toplevel//", 2, 4).
Extra spaces do not affect the semantics of OCaml programs. There are also no statements per se in OCaml - everything is an expression. To evaluate two expressions in a sequence you may use the semicolon, e.g.,
print_endline "Hello";
assert (1 > 2);
print_endline "World";
You can also use let .. in .. to chain expressions, especially, if you need to the expression values, e.g.,
let x = 1 + 2 in
let y = 3 + 4 in
Format.printf "%d + %d = %d\n" x y (x + y)
Going back to your example, it should be
let rec fib n =
assert (n >= 0);
if n = 1 then 1
else n * fib (n - 1)
P.S. The double semicolons are not really a part of the language but a special input sequence to be used in the interactive toplevel.

Syntax error when Calling function inside function in Ocaml

I am getting a Syntax error when calling the function f and g inside lp and assigning them to y and z
let lp m =
let y = f m in
let z = g y (List.length y) m;
Here's my full code:
open Printf
open Format
let regraUm m = m/2
let regraDois m = ((m / 10) mod 10) * (m mod 10)
let regraTres m = 42
let f m =
let list = ref [] in
if ((m mod 2) = 0) then list := 1::!list;
if ((m mod 3) = 0) || ((m mod 4) = 0) then list := 2::!list;
if ((m mod 5) = 0) then list := 3::!list;
!list
let g list len m =
let res = ref [] in
for i = 0 to (len-1) do
let regra = List.nth list i in
if (regra = 1) then res := (m - (regraUm m))::!res;
if (regra = 2) || ((m mod 4) = 0) then res := (m - (regraDois m))::!res;
if (regra = 3) then res := (m - (regraTres m))::!res;
done;
!res
let lp m =
let y = f m in
let z = g y (List.length y) m;
Syntax Error:
ocamlopt regras.ml -o r
File "regras.ml", line 33, characters 4-4:
Error: Syntax error
f and g work properly when used outside of a function.
A let binding need some expression to be attached after an in, which in your case doesn't exist. In this case your code would work either adding z as expression or removing the binding leaving just the expression.
let lp m =
let y = f m in
let z = g y (List.length y) m in
z
Or this
let lp m =
let y = f m in
g y (List.length y) m

The 'op' operator in SML

So I came across with the op operator and I don't get the pupurse.
I defined two functions:
fun op pow1 (x,y) = Math.pow (x,y);
fun pow2 (x,y) = Math.pow (x,y);
They both have the same signatures:
val pow1 = fn : real * real -> real
val pow2 = fn : real * real -> real
And they both have the same function calls:
pow1 (5.0,6.0);
> val it = 15625.0 : real
pow2 (5.0,6.0);
> val it = 15625.0 : real
So what is the difference between those two functions? What is the idea behind op?
The op keyword undoes the infix status of the following (alphanumerical or symbolic) identifier. For example:
val n = op+ (1, 2) (* equivalent to: val n = 1 + 2 *)
val m = op mod (5, 6) (* equivalent to: val m = 5 mod 6 *)
fun op+ (x, y) = x - y (* equivalent to: fun x + y = x - y *)
These lines would be syntax errors otherwise.
This is useful when referring to a normally-infix function without immediately invoking it, such as when passing it to a higher-order function. For example:
List.foldr op+ 0 [1, 2, 3] (* equivalent to: 1 + (2 + (3 + 0)) *)

How can I divide two numbers in ML defined as a datatype?

I'm trying to write a recursive function in SML that receives two natural numbers n1,n2 and returns the result of n1 div n2
The datatype natural is defined as follows:
datatype natural = zero | Succ of natural
I want to write it in terms of the new datatype , or in other words, not by converting them to their regular form and converting back the result.
Any ideas how division is done in this definition?
You could start by defining subtraction:
exception Negative
fun sub (a, zero) = a
| sub (zero, b) = raise Negative
| sub (Succ a, Succ b) = sub (a, b)
From here, it should be pretty easy to simply count how many times you can subtract n2 from n1 without going negative. In particular, this equation should help:
n1 div n2 = 1 + (n1 - n2) div n2
I'll leave the rest to you.
Similar to Sam Westrick's definition, "number of times you can subtract n2 from n1 without going negative", you could also do integer division with addition and greater-than using the definition, "number of times you can add n2 to itself before it is greater than n1."
datatype nat = Z | S of nat
fun gt (S x, S y) = gt (x, y)
| gt (S _, Z) = true
| gt (Z, _) = false
fun add (x, Z) = x
| add (x, S y) = add (S x, y)
fun divide (_, Z) = raise Domain
| divide (x, y) = (* ... *)
Addition might seem like a conceptually simpler thing than subtraction. But greater-than is a more expensive operator than determining when a number is negative, since the case is incurred by induction, so Sam's suggestion would be more efficient.
You might test your solution with the following tests:
fun int2nat 0 = Z
| int2nat n = S (int2nat (n-1))
fun nat2int Z = 0
| nat2int (S n) = 1 + nat2int n
fun range (x, y) f = List.tabulate (y - x + 1, fn i => f (i + x))
fun divide_test () =
let fun showFailure (x, y, expected, actual) =
Int.toString x ^ " div " ^ Int.toString y ^ " = " ^
Int.toString expected ^ ", but divide returns " ^
Int.toString actual
in List.mapPartial (Option.map showFailure) (
List.concat (
range (0, 100) (fn x =>
range (1, 100) (fn y =>
let val expected = x div y
val actual = nat2int (divide (int2nat x, int2nat y))
in if expected <> actual
then SOME (x, y, expected, actual)
else NONE
end))))
end

Confusing SML statement

I have this statement:
let val x =
let val x = 5
in(fn y =>(y,x+y))
end
in
let val y=3 and z=10
in x z
end
end;
The output is :
(10,15)
I've been trying to track how this answer was produced but am getting confused. Is there a better way to write this that would help me understand what variables are being used where? Thank you!
First, some alpha-conversion:
let val fnPairOfInputAndInputPlus5 =
let val five = 5
in ( fn input => ( input, five + input ) )
end
in let val ignored = 3 and input = 10
in fnPairOfInputAndInputPlus5 input
end
end;
This code is demonstrating that when you declare a function value, unbound values in the declaring scope, such as the value five, are "enclosed" by the declaration (hence the term "closures"). Thus the function always returns a pair consisting of its input and its input plus five.
You could simplify it to
let fun f y = (y,5+y)
val y=3 and z=10
in
f z
end;
Note that the two instances of y are independent. The inner occurrence of x (which I've eliminated) is independent of the outer one (now renamed f).
Can be understood using manual evaluation with detailed explanations.
Starting with your initial expression:
let val x =
let val x = 5
in (fn y => (y,x + y))
end
in
let val y = 3 and z = 10
in x z
end
end;
Line 2,3,4 is an expression whose type is a function, as you see in the in part. It does not depends on any outer context, so it may be simplified as just fn y => (y, 5 + y), substituting x to 5, according to the binding given in let.
So you now have this:
let val x = fn y => (y, 5 + y)
in
let val y = 3 and z = 10
in x z
end
end;
After substitution of x (and removal of the let which in then now not necessary any more):
let val y = 3 and z = 10
in (fn y => (y, 5 + y)) z
end;
Note the y appearing in (y, 5 + y) are bound to the function's argument, and not to 3. There is no reference to this outer y, so its biding may be removed.
Now you have:
let z = 10
in (fn y => (y, 5 + y)) z
end;
Substituting z to 10 and removing the let which is not necessary any more, you get:
(fn y => (y, 5 + y)) 10;
This is a function application. You may evaluate it, to get:
(10, 5 + 10);
Which gives the final and constant result you noticed:
(10, 15);