Hi,
First of all, I should mention that F# doesn't make difference between statements and expressions - statement in F# is just an expression that returns a type "unit". When you have a block of F# code with multiple "statements", it just means that it is a sequence of expressions (where the first expressions return unit and the last can return some value). For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// the whole let is an expression 
<@ let a = 1 in (a + 1) @>

// the following (alone) doesn't make any sense, 
//because it is missing the part after 'in'
<@ let b = 2 @>

// simple expression of type 'int'
<@ 1 + 2 @>

// simple expression of type 'unit'
<@ printf "hello" @>

// sequence of expressions
<@ printf "hello"; 1 + 2 @>

// same thing written using the #light syntax
<@
  printf "hello"
  1 + 2
@>

Now, you can see that when traversing the quotation, you'll have to recursively call the traverse function on all expressions in the sequence of expressions (if the quotation contains Seq) or call it recursively on the body of let binding (if the quotation conains Let).

The following demonstrates a simple recursive function that does this correctly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
#light
open Microsoft.FSharp.Quotations.Raw

let rec print expr = 
  match expr with
  | Let((var,value), body) -> 
      // Represents: let <var> = <value> in <body>
      printf "let %s = " var.Text 
      print value
      printf "\n"
      print body
  | Int32(n) ->
      // Represents a number
      printf "%d" n
  | GenericTopDefnApp <@@ (+) @@> (ty, a::b) ->
      // Represents: <a> + <b>
      print a
      printf " + "
      print a
  | Var(v) ->
      // Represents variable reference
      printf "%s" v.Text
  | Seq(a,b) -> 
      // Represents: <a>; <b> (sequence expression)
      print a
      printf ";\n"
      print b
  | _ -> 
      printf "<something else>"

And the following code is an example that contains "let" binding and a sequence (the "printf" call isn't handled in the traverse function, so it prints "<something else>" instead of printf):

1
2
3
4
5
6
7
8
9
10
11
 
let expr = 
  <@@ 
    let a = 1  
    let b = 2
    printf "hello" 
    a + b 
  @@>


print expr
By on 8/18/2007 7:04 AM ()

Thank you. I was missing the sequence.

Beautifully explained. Great blog posts too.

Cheers

Bart

By on 8/18/2007 8:05 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper