Tom Stevens
Tom Stevens

Reputation: 335

OCaml keyword "in"

Where is the difference, I do not understand the purpose of the in keyword

let pow x =x*x;;
let y = 3;;
pow 3 + y;;

let pow x =x*x in 
let b = 3 in
pow 3 + b;;

Upvotes: 0

Views: 166

Answers (3)

Tom Stevens
Tom Stevens

Reputation: 335

Thanks for your answers, these helped me to come to following short answer (as Nalin Ranjan mentioned in the comment above:

it is the ocamls way of scoping

enter image description here

let pow x =x*x;; (* global scope *)
pow 3;;

let pow2 x =x*x in (* local sope *)
pow2 3 + pow 4;; (* pow2 is only available here*)

pow 2;; 
pow2 2;; (* not available here *)

Please correct me if I'm wrong.

Upvotes: 3

Chris
Chris

Reputation: 36451

To augment @JeffreyScofield's answer, let ... in ... provides an excellent tool to organize your code and keep it tidy.

Consider making a trivial recursive function to sum a list of integers.

let rec sum lst =
  match lst with
  | [] -> 0
  | x::xs -> x + sum xs

But then you get a little further into your studies of functional programming and decide it would be best if sum were tail-recursive, so you need a helper function that takes an accumulator, and then sum simply needs to call that function.

let rec sum_helper lst acc =
  match lst with
  | [] -> acc
  | x::xs -> sum_helper xs (x + acc)

let sum lst = sum_helper lst 0

But you don't really need sum_helper except in the context of sum, and having it hang out accessible at the toplevel clutters your namespace, so you can use let ... in ... to solve this.

let sum lst = 
  let rec sum_helper lst acc =
    match lst with
    | [] -> acc
    | x::xs -> sum_helper xs (x + acc)
  in
  sum_helper lst 0

Upvotes: 3

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66818

The declaration let <var> = <expr> can appear only at the top level of a module. It's used to define a global name of the module. If you imagine your two examples as independent modules, the first one declares two global names, pow and y.

The expression let <var> = <expr1> in <expr2> is just an expression in which var is a local variable. In your second example you are declaring no global names.

When typing into the toplevel, you are defining a module. But the module tends to fly by while you're thinking of other things. So you might not notice the difference. If you put your two examples into separate files named a.ml and b.ml, there would be easily observable differences. Namely, the names A.pow and A.y would be defined, but there would be no global names defined in module B.

Upvotes: 3

Related Questions