4

I am learning Jason Hickey's Introduction to Objective Caml. Just have a question about the expression thing.


So it says:

Definitions using let can also be nested using the in form.

let identifier = expression1 in expression2 The expression expression2 is called the body of the let. The variable named identifier is defined as the value of expression1 within the body. The identifier is defined only in the body expression2 and not expression1.

A let with a body is an expression; the value of a let expression is the value of the body.

let x = 1 in
    let y = 2 in
        x + y;;


let z =
    let x = 1 in
        let y = 2 in
            x + y;;

val z : int = 3


Ok. I don't understand much about the above statements.

First

The variable named identifier is defined as the value of expression1 within the body. The identifier is defined only in the body expression2 and not expression1.

What does this mean? So identifier is the value of expression1, but only in the body expression2? Does it mean that identifier is effective only in expression2but has the value of expression1? Then does defining identifier make sense, as it is only in expression2?

Second

Let's see the example:

let x = 1 in
    let y = 2 in
        x + y;;

So I don't see the point of this let statement. x = 1 for sure, what's the point of giving a body of let y=2 in x+y;;?

Third

let z = let x = 1 in let y = 2 in x + y;;

So how can I sort out the logic of this statement?

if take this definition form: let identifier = expression1 in expression2

What's the expression1 in the let statement above? Is it let x = 1?


Can anyone tell me the logic of nesting let in a kind of Java way? or more understandable way?

Jackson Tale
  • 25,428
  • 34
  • 149
  • 271
  • A `C` sequence of statements `x = 1; y = 2; return x + y;` is translated into ML `let x = 1 in y = 2 in x + y`. Remember, there are no statements in ML, everything is an expression. – SK-logic Nov 30 '12 at 17:17
  • The logic is very simple - think of `let x = y in z` as a syntax sugar for `(fun x -> z) y`. – SK-logic Nov 30 '12 at 17:18
  • `let`s are just ways to define values within the scope of the body. – nlucaroni Nov 30 '12 at 17:22

2 Answers2

4

What does this mean? So identifier is the value of expression1, but only in the body expression2? Does it mean that identifier is effective only in expression2, but has the value of expression1?

Yes. When I do let x = 42 in x+x, then x has the value 42 in the expression x+x, but x doesn't have any value outside of the let expression. So if you typed something like this in the interpreter:

let x = 42 in x+x;;
x*2;;

The result of x+x would be 84, but the result of x*2 would be an error because x is not defined in that scope.

Then does defining identifier make sense, as it is only in expression2?

Sure, why not? I mean in this specific example where x is defined to be a single number, it might not make all that much sense, but in a real world scenario, it would probably be a larger expression and not having to repeat it multiple times becomes a big advantage.

Also expression1 might have side-effects that you only want to execute once (e.g. if you want to assign user-input to a variable).

So I don't see the point of this let statement. x = 1 for sure, what's the point of giving a body of let y=2 in x+y;;?

You mean: why not just write 1+2? Again, in a real world scenario you'll have more complicated expressions and you don't want to have them all on one line. Also giving names to values generally increases readability (though not really in this example).

let z = let x = 1 in let y = 2 in x + y;;

What's the expression1 in the let statement above? Is it let x = 1?

Here let z = ... is a let statement, i.e. it defines the name z globally and doesn't have a body. So the entire expression to the right of the first = is the value of z. For the let x = ... in ... bit, 1 is the expression1 and let y = 2 in x+y is the expression2. And for y 2 is the expression1 and x+y is the expression2.

sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • So if I say `let x = 12;;`, then the `x` is defined and I can use it later anywhere. If I say `let x = 12 in x+x', then `x` is defined and can be used in only `x+x`, am I correct? – Jackson Tale Nov 30 '12 at 17:31
  • Thanks. ok then, about the `z` part of example, the true important part is `the later x+y`. And for `let z` there is no `body of let`, the whole `let x=1 in let y =2 in x+y` is an expression. Am I right? – Jackson Tale Nov 30 '12 at 17:36
  • Thanks sepp2k. So then how do I tell `a let is a expression` or `a let is a binding (by binding, I mean defining an identifier)` – Jackson Tale Nov 30 '12 at 17:40
  • @JacksonTale A `let` expression always has an `in` while a global `let` binding does not. Also global `let` bindings are only allowed at the top-level, not inside an expression. So if there are more `let`s than there are `in`s, then the first `let` must be a global binding. – sepp2k Nov 30 '12 at 17:43
  • `Also global let bindings are only allowed at the top-level`. what do you mean by `top-level` here? Is it the command line interaction thing of OCaml? – Jackson Tale Nov 30 '12 at 17:51
  • @JacksonTale I meant "not as part of a larger expression". – sepp2k Nov 30 '12 at 17:52
  • Thanks sepp2k, no more questions – Jackson Tale Nov 30 '12 at 17:57
1

What does this mean? So identifier is the value of expression1, but only in the body expression2? Does it mean that identifier is effective only in expression2but has the value of expression1? Then does defining identifier make sense, as it is only in expression2?

That's what it means, yes, but more simply stated, it means that you cannot use the identifier "in its own value". After you bind the value of expression1 to the identifier you can then use the identifier instead of the whole of expression1, in expression2.

Generally, there are two reasons for using bindings; 1 is to prevent multiple evaluations of a given expressions, and 2 is for clarity: it's often useful to give the value of a relatively complex expression a human-readable name.

In terms of Java, a let binding corresponds roughly to a local variable.

Joost Diepenmaat
  • 17,633
  • 3
  • 44
  • 53