3

I've been trying to get my head round various bits of F# (I'm coming from more of a C# background), and parsers interest me, so I jumped at this blog post about F# parser combinators:

http://santialbo.com/blog/2013/03/24/introduction-to-parser-combinators

One of the samples here was this:

/// If the stream starts with c, returns Success, otherwise returns Failure
let CharParser (c: char) : Parser<char> =
    let p stream =
        match stream with
        | x::xs when x = c -> Success(x, xs)
        | _ -> Failure
    in p               //what does this mean?

However, one of the things that confused me about this code was the in p statement. I looked up the in keyword in the MSDN docs:

http://msdn.microsoft.com/en-us/library/dd233249.aspx

I also spotted this earlier question:

Meaning of keyword "in" in F#

Neither of those seemed to be the same usage. The only thing that seems to fit is that this is a pipelining construct.

Community
  • 1
  • 1
JohnL
  • 3,922
  • 3
  • 22
  • 22

2 Answers2

8

The let x = ... in expr allows you to declare a binding for some variable x which can then be used in expr.

In this case p is a function which takes an argument stream and then returns either Success or Failure depending on the result of the match, and this function is returned by the CharParser function.

The F# light syntax automatically nests let .. in bindings, so for example

let x = 1
let y = x + 2
y * z

is the same as

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

Therefore, the in is not needed here and the function could have been written simply as

let CharParser (c: char) : Parser<char> =
    let p stream =
        match stream with
        | x::xs when x = c -> Success(x, xs)
        | _ -> Failure
    p
Lee
  • 142,018
  • 20
  • 234
  • 287
  • Thanks, so it is the same use case as the SO question I had a link to, though the code layout was slightly different. – JohnL Mar 31 '13 at 10:51
8

The answer from Lee explains the problem. In F#, the in keyword is heritage from earlier functional languages that inspired F# and required it - namely from ML and OCaml.

It might be worth adding that there is just one situation in F# where you still need in - that is, when you want to write let followed by an expression on a single line. For example:

let a = 10
if (let x = a * a in x = 100) then printfn "Ok"

This is a bit funky coding style and I would not normally use it, but you do need in if you want to write it like this. You can always split that to multiple lines though:

let a = 10
if ( let x = a * a
     x = 100 ) then printfn "Ok"
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • Yeah the use of in really does not make that any more readable. I take it that in your example doing something like `if ( a * a = 100 ) then printfn "Ok"` would achieve the same thing? – JohnL Mar 31 '13 at 12:15