syntax error while loop in OCaml - while-loop

What's the problem with the code below? I'am struggling a lot with knowing when to use ';' or ';;' or use begin end in OCaml. Here i need to read some edges and insert into graph but i need to link this with rest of program so that it can use g(a graph) with all the edges.
When i do this it says Error: Syntax error
let i = ref n in
while !i > 0 do
(
let pair = read_edge Scanning.stdin in
let g = insert_edge (fst pair) (snd pair) g in
i := !i - 1
)
done in (* giving error in this line *)
let rec do_stuff l =
match l with
| [] -> ()
| h::t -> print_int h;do_stuff t in
( * more functions)

in is part of the syntax of let (it's "let" pattern "in" expression). The syntax of a while loop is simply "while" expression "do" expression "done", so there's no in in there.
To make your code compile you can replace in with a ;, so it executes the while loop followed by the let expression after it. However it seems strange to me that you'd have a while loop between a bunch of function definitions.
Also note that in the loop you do let g = ..., but then you're not using g anywhere in the let's body. So that binding accomplishes nothing.

Related

Getting the name of a function in a macro

I wrote a macro to make code cleaner and clearer by using error message templates stored in a dict. In this example it inserts name of the function, see discourse and #__FUNCTION__, that throws the error.
exception = Dict(:foo => ("bar ~", ArgumentError))
macro ⛔(id)
msg, type = exception[id]
quote
msg = replace($msg, "~" => StackTraces.stacktrace()[1].func)
throw($type(msg))
end
end
This works fine in f that uses positional arguments,
f(x, p) = p < 5 ? x : #⛔ foo
f(1, 10)
#> ERROR: ArgumentError: bar f
but displays #..# when a keyword argument is used.
g(x; p = 3) = p < 5 ? x : #⛔ foo
g(1, p = 10)
#> ERROR: ArgumentError: bar #g#N
Here N is the nth expression evaluated in the session. Redefining g with the same syntax increments this number.
I am stuck after I couldn't spot a difference between the code produced by #⛔.
#macroexpand function f(x, p) p < 5 ? x : #⛔ foo end
#macroexpand function g(x; p = 3) p < 5 ? x : #⛔ foo end
Question
What is happening in g that is different from f?
That is the name of the method the expanded code is called in -- definitions with keyword arguments are lowered to dispatch helper methods called "keyword sorters": https://docs.julialang.org/en/v1/devdocs/functions/#Keyword-arguments. These make keywords arguments use dispatch (internally) and compilation just as other functions, instead of just dictionary lookup as e.g. in Python.
I don't think you can do what you want easily in that case, as the conversion process always happens. Taking a previous stack frame would work, but then you have to know whether you are within a keyword method beforehand.
Maybe the following approach works: pattern match the method name (#<f>#<N>), and then check whether it is an actual kwsorter method of any method of f. If so, proceed with f.

OCaml Syntax Error fixed by double semicolon

I'm sorry for asking such a basic question here, but I'm getting a syntax error when trying to compile the following code,
let sum_of_squares_of_two_largest x y z =
let a :: b :: _ = List.sort (fun x y -> -(compare x y)) [x; y; z] in
a * a + b * b;
let rec factorial n =
if n = 0 then 1 else n * factorial (n - 1);
let e_term n = 1.0 /. float_of_int (factorial n);
let rec e_approximation n =
if n = 0 then (e_term 0) else (e_term n) +. (e_approximation (n - 1));
let rec is_even x = if x = 0 then true else is_odd (x - 1);
and is_odd x = not (is_even x);
let rec f_rec n =
if n < 3 then n else f_rec(n - 1) + 2 * f_rec(n - 2) + 3 * f_rec(n - 3);
The uninformative compiler tells me there is syntax error on line 19, which is the last line of the file.
File "source.ml", line 19, characters 0-0:
Error: Syntax error
That is, line 19 is a blank line, only with a new-line character.
I can "fix" this syntax error by adding ;; at the end of each function definition instead of the ;.
Am I missing a semicolon somewhere?
As has been pointed out in the comments, ; is not a statement terminator like in many other (Algol-inspired) languages, but a sequence operator. It takes two values, throws away the first (but warns if it is not unit) and returns the second. a; b is therefore roughly equivalent to let _ = a in b.
You say you would have expected the error to say something like ';' is missing the second operand., but the thing is: it doesn't. Not until it reaches the end of the file (at which point the error message certainly could have been more intelligent, but probably not very accurate anyway).
What follows each ; in your code looks like a perfectly valid expression that might yield a value. For example, if let rec factorial n = ...; had been let rec factorial n = ... in 2 The value of the expression would have been 2. The problem here, from the compiler's point of view, is that it runs out of file before the expression is finished.
As you've also found out, ;; actually is a statement terminator. Or perhaps a toplevel definition terminator is a better term (I don't know if it even has an official name). It's used in the REPL to terminate input, but isn't needed in normal OCaml code unless you mix toplevel definitions and expressions, which you never should.
;; can still be useful for beginners as a "bulkhead", however. If you put just one ;; in place of a ; in the middle of your file, you'll find the compiler now points the error location there. That's because ;; terminates the definition without the preceding expression being complete. So you now know there's an error before that. (Actually in the preceding expression, but since your entire file is one single expression, "before that" is really the best we can do).

Destructuring a list with equations in maxima

Say that I have the following list of equations:
list: [x=1, y=2, z=3];
I use this pattern often to have multiple return values from a function. Kind of of like how you would use an object, in for example, javascript. However, in javascript, I can do things like this. Say that myFunction() returns the object {x:1, y:2, z:3}, then I can destructure it with this syntax:
let {x,y,z} = myFunction();
And now x,y,z are assigned the values 1,2,3 in the current scope.
Is there anything like this in maxima? Now I use this:
x: subst(list, x);
y: subst(list, y);
z: subst(list, z);
How about this. Let l be a list of equations of the form somesymbol = somevalue. I think all you need is:
map (lhs, l) :: map (rhs, l);
Here map(lhs, l) yields the list of symbols, and map(rhs, l) yields the list of values. The operator :: means evaluate the left-hand side and assign the right-hand side to it. When the left-hand side is a list, then Maxima assigns each value on the right-hand side to the corresponding element on the left.
E.g.:
(%i1) l : [a = 12, b = 34, d = 56] $
(%i2) map (lhs, l) :: map (rhs, l);
(%o2) [12, 34, 56]
(%i3) values;
(%o3) [l, a, b, d]
(%i4) a;
(%o4) 12
(%i5) b;
(%o5) 34
(%i6) d;
(%o6) 56
You can probably achieve it and write a function that could be called as f(['x, 'y, 'z], list); but you will have to be able to make some assignments between symbols and values. This could be done by writing a tiny ad hoc Lisp function being:
(defun $assign (symb val) (set symb val))
You can see how it works (as a first test) by first typing (form within Maxima):
:lisp (defun $assign (symb val) (set symb val))
Then, use it as: assign('x, 42) which should assign the value 42 to the Maxima variable x.
If you want to go with that idea, you should write a tiny Lisp file in your ~/.maxima directory (this is a directory where you can put your most used functions); call it for instance myfuncs.lisp and put the function above (without the :lisp prefix); then edit (in the very same directory) your maxima-init.mac file, which is read at startup and add the two following things:
add a line containing load("myfuncs.lisp"); before the following part;
define your own Maxima function (in plain Maxima syntax with no need to care about Lisp). Your function should contain some kind of loop for performing all assignments; now you could use the assign(symbol, value) function for each variable.
Your function could be something like:
f(vars, l) := for i:1 thru length(l) do assign(vars[i], l[i]) $
which merely assign each value from the second argument to the corresponding symbol in the first argument.
Thus, f(['x, 'y], [1, 2]) will perform the expected assigments; of course you can start from that for doing more precisely what you need.

Does "<-" mean assigning a variable in Haskell?

Just started Haskell, it's said that everything in Haskell is "immutable" except IO package. So when I bind a name to something, it's always something immutable? Question, like below:
Prelude> let removeLower x=[c|c<-x, c `elem` ['A'..'Z']]
Prelude> removeLower "aseruiiUIUIdkf"
"UIUI"
So here:
1. “removeLower" is an immutable? Even it's a function object?
But I can still use "let" to assign something else to this name.
2. inside the function "c<-x" seems that "c" is a variable.
It is assigned by list x's values.
I'm using the word "variable" from C language, not sure how Haskell name all its names?
Thanks.
If you're familiar with C, think of the distinction between declaring a variable and assigning a value to it. For example, you can declare a variable on its own and later assign to it:
int i;
i = 7;
Or you can declare a variable and assign initial value at the same time:
int i = 7;
And in either case, you can mutate the value of a variable by assigning to it once more after the first initialization or assignment:
int i = 7; // Declaration and initial assignment
i = 5; // Mutation
Assignment in Haskell works exclusively like the second example—declaration with initialization:
You declare a variable;
Haskell doesn't allow uninitialized variables, so you are required to supply a value in the declaration;
There's no mutation, so the value given in the declaration will be the only value for that variable throughout its scope.
I bolded and hyperlinked "scope" because it's the second critical component here. This goes one of your questions:
“removeLower" is an immutable? Even it's a function object? But I can still use "let" to assign something else to this name.
After you bind removeLower to the function you define in your example, the name removeLower will always refer to that function within the scope of that definition. This is easy to demonstrate in the interpreter. First, let's define a function foo:
Prelude> let foo x = x + 2
Prelude> foo 4
6
Now we define an bar that uses foo:
Prelude> let bar x = foo (foo x)
Prelude> bar 4
8
And now we "redefine" foo to something different:
Prelude> let foo x = x + 3
Prelude> foo 4
7
Now what do you think happens to bar?
Prelude> bar 4
8
It remains the same! Because the "redefinition" of foo doesn't mutate anything—it just says that, in the new scope created by the "redefinition", the name foo stands for the function that adds three. The definition of bar was made in the earlier scope where foo x = x + 2, so that's the meaning that the name foo has in that definition of bar. The original value of foo was not destroyed or mutated by the "redefinition."
In a Haskell program as much as in a C program, the same name can still refer to different values in different scopes of the program. This is what makes "variables" variable. The difference is that in Haskell you can never mutate the value of a variable within one scope. You can shadow a definition, however—uses of a variable will refer to the "nearest" definition of that name in some sense. (In the case of the interpreter, the most recent let declaration for that variable.)
Now, with that out of the way, here are the syntaxes that exist in Haskell for variable binding ("assignment"). First, there's top-level declarations in a module:
module MyLibrary (addTwo) where
addTwo :: Int -> Int
addTwo x = x + 2
Here the name addTwo is declared with the given function as its value. A top level declaration can have private, auxiliary declarations in a where block:
addSquares :: Integer -> Integer
addSquares x y = squareOfX + squareOfY
where square z = z * z
squareOfX = square x
squareOfY = square y
Then there's the let ... in ... expression, that allows you to declare a local variable for any expression:
addSquares :: Integer -> Integer
addSquares x y =
let square z = z * z
squareOfX = square x
squareOfY = square y
in squareOfX + squareOfY
Then there's the do-notation that has its own syntax for declaring variables:
example :: IO ()
example = do
putStrLn "Enter your first name:"
firstName <- getLine
putStrLn "Enter your lasst name:"
lastName <- getLine
let fullName = firstName ++ " " ++ lastName
putStrLn ("Hello, " ++ fullName ++ "!")
The var <- action assigns a value that is produced by an action (e.g., reading a line from standard input), while let var = expr assigns a value that is produced by a function (e.g., concatenating some strings). Note that the let in a do block is not the same thing as the let ... in ... from above!
And finally, in list comprehension you get the same assignment syntax as in do-notation.
It's referring to the monadic bind operator >>=. You just don't need to explicitly write a lambda as right hand side parameter. The list comprension will be compiled down to the monadic actions defined. And by that it means exactly the same as in a monadic environment.
In fact you can replace the list comprension with a simple call to filter:
filter (`elem` ['A' .. 'Z']) x
To answer your question regarding the <- syntactic structure a bit clearer:
[c| c <- x]
is the same as
do c <- x
return c
is the same as
x >>= \c -> return c
is the same as
x >>= return
Consider the official documentation of Haskell for further reading: https://hackage.haskell.org/package/base-4.8.2.0/docs/Control-Monad.html#v:-62--62--61-
[c|c<-x, c `elem` ['A'..'Z']]
is a list comprehension, and c <- x is a generator where c is a pattern to be matched from the elements of the list x. c is a pattern which is successively bound to the elements of the input list x which are a, s, e, u, ... when you evaluate removeLower "aseruiiUIUIdkf".
c `elem` ['A'..'Z']
is a predicate which is applied to each successive binding of c inside the comprehension and an element of the input only appears in the output list if it passes this predicate.

Syntax errors in sml: Inserting LOCAL

The following method determines how many numbers can be added up starting from the beginning of the list without adding up to 4:
number_before_Reaching_sum (4, [1,2,3,4,6]);
should return : val it = 2 : int
fun number_before_reaching_sum (sum : int * int list) =
let val len_orig_list = length (#2 sum)
in fun num_bef_reach_sum (sum) =
if #1 sum <= 0
then len_orig_list - (length (#2 sum)) - 1
else num_bef_reach_sum (#1 sum - hd (#2 sum), tl (#2 sum))
end
syntax error: inserting LOCAL
syntax error found at EOF
I can't seem to find the errors in this code. I have some experience with Python, but just starting to learn sml. I'm loving it, but I don't understand all the error messages. I have really spent hours on this, but I think I don't know enough to solve my problem. I tried exchanging let with local, but i still got a syntax error (equalop). I think that the function between in and end is an expression and not a declaration. But I would appreciate any comments on this. If you come up with alternative code, it would be great if you did it without using more advanced features, since I'm just trying to get the basics down :-)
You probably meant this:
fun number_before_reaching_sum (sum : int * int list) =
let
val len_orig_list = length (#2 sum)
fun num_bef_reach_sum (sum) =
if #1 sum <= 0
then len_orig_list - (length (#2 sum)) - 1
else num_bef_reach_sum (#1 sum - hd (#2 sum), tl (#2 sum))
in
num_bef_reach_sum (sum)
end
With let … in … end, the part between let and in is for the local definitions; the part between in and end is for the expression which will be the evaluation of the let … in … end expression (this construct is indeed an expression).
Think of let … in … end as a possibly complex expression. You hoist parts of the expression as definitions, then rewrite the complex expression using references to these definitions. This help write shorter expressions by folding some of its sub‑expressions. This construct is also required when recursion is needed (a recursion requires a defining name).
Another way to understand it, is as the application of an anonymous function whose arguments bindings are these definitions.
Ex.
let
val x = 1
val y = 2
in
x + y
end
is the same as writing
(fn (x, y) => x + y) (1, 2)
which is the same as writing
1 + 2
You erroneously put a definition at the place of the expression the whole evaluates to.
(note I did not check the function's logic, as the question was about syntax)