views:

45

answers:

3

Hello!

I'm learning OCaml and although I have years of experience with imperative programming languages (C, C++, Java) I'm getting some problems with delimiters between declarations or expressions in OCaml syntax.

Basically I understood that I have to use ; to concatenate expressions and the value returned by the sequence will be the one of last expression used, so for example if I have

exp1; exp2; exp3

it will be considered as an expression that returns the value of exp3. Starting from this I could use

let t = something in exp1; exp2; exp3

and it should be ok, right?

When am I supposed to use the double semicol ;;? What does it exactly mean?

Are there other delimiters that I must use to avoid syntax errors?

I'll give you an example:

let rec satisfy dtmc state pformula = 
  match (state, pformula) with
    (state, `Next sformula) ->
        let s = satisfy_each dtmc sformula
        and adder a state = 
            let p = 0.; 
            for i = 0 to dtmc.matrix.rows do
                    p <- p +. get dtmc.matrix i state.index
            done;
            a +. p
        in
            List.fold_left adder 0. s
      | _ -> []

It gives me syntax error on | but I don't get why.. what am I missing? This is a problem that occurs often and I have to try many different solutions until it suddently works :/

A side question: declaring with let instead that let .. in will define a var binding that lasts whenever after it has been defined?

What I basically ask is: what are the delimiters I have to use and when I have to use them. In addition are there differences I should consider while using the interpreter ocaml instead that the compiler ocamlc?

Thanks in advance!

+2  A: 
let p = 0.; 

This is the error. The ; needs to be an in. You can't use let without in only to define global functions, you can't use it inside an expression.

A side question: declaring with let instead that let .. in will define a var binding that lasts whenever after it has been defined?

You can only ever use one or the other (except in the interactive interpreter where you are allowed to mix expressions and definitions). When defining a global function or value, you need let without in. Inside an expression you need let with in.

sepp2k
I tried may way before posting my code. But when I tried `let p = 0. in for ... done; a +. p` it was telling me that `p` inside for loop was unbound. That's why I'm getting crazy.. it shouldn't be unbound since it's of the form `let something in exp1; exp2`. It should know `something` inside the for loop :/
Jack
+2  A: 

;; is used to terminate input and start interpreting in ocaml REPL, it has no special meaning when compiling with ocamlc or ocamlopt.

You cannot assign to arbitrary value with <- operator, you have to use ref type for mutable variables:

let p = ref 0. in
for i = 0 to dtmc.matrix.rows do
    p := !p +. get dtmc.matrix i state.index
done;
a +. !p
rkhayrov
ok, now it's getting clearer. Thanks to both of you.. just +1 each :)The problem is when you mix errors and you are not able to understand what's really happening, OCaml is really different from what I'm used to and no "cheatsheet" is available..
Jack
;; has the same meaning for ocamlc/ocamlopt as in REPL - to delimit toplevel phrases. And indeed it can be quite useful when dealing with syntax errors to explicitely mark end of each toplevel definition and see if compiler agrees :)
ygrek
+2  A: 

The ;; delimiter terminates a top-level entity. In the ocaml toplevel (interpreter), it signals to the interpreter that a particular piece of input is finished and should be evaluated.

In programs to be compiled with ocamlc or ocamlopt, you don't need it near as often, as consecutive top-level let (without in), module, type, exception, and similar statements automatically signal the beginning of a new "phrase". If you include a top-level expression in a module that is to be evaluated only for its side-effects (such as generating some output or registering a module), you'll need a ;; before it to tell the compiler to stop compiling the previous phrase and start compiling a new thing. Otherwise, if the previous thing is a let, it will assume that the new expression is part of the let. For example:

let msg = "Hello, world";; (* we need ;; here *)
print_endline msg;; (* ;; is optional here, unless we have another expression *)

When you do and don't need ;; is somewhat subtle, so I usually terminate all my module-level entities with it so I don't have to worry about when it is and isn't needed.

; is used to separate sequential "statements" within a single expression. So foo; bar is a single sequential expression composed of foo and bar, while foo;; bar is only valid at the top level of a module and signifies two expressions.

On let without in: that construct is only valid in a module definition and variables so bound will be bound through the end of the module. Often, this is just the end of the file; if you have nested modules, however, its scope can be more limited. It does not work inside another expression or definition such as a function definition, unless it is within a local module definition.

Michael E