If I run the first example from MSDN (https://msdn.microsoft.com/en-us/library/dd233212.aspx) in the F# Interactive window, I get the expected output:
fun (x:System.Int32) -> x + 1
a + 1
let f = fun (x:System.Int32) -> x + 10 in f 10
But if I run it in the Main from my program, all let bindings are replaced by their constant values:
[<EntryPoint>]
let main argv =
let a = 2
// exprLambda has type "(int -> int)".
let exprLambda = <@ fun x -> x + 1 @>
// exprCall has type unit.
let exprCall = <@ a + 1 @>
println exprLambda
println exprCall
println <@@ let f x = x + 10 in f 10 @@>
Result:
fun (x:System.Int32) -> x + 1
2 + 1
let f = fun (x:System.Int32) -> x + 10 in f 10
Is this normal or a bug? Are the rules for this documented? What can I do to force it to the expected output?
Edit:
This answer (https://stackoverflow.com/a/4945137/1872399) states (Variables are automatically replaced with values if the variable is defined outside of the quotation).
but I couldn't find any mention of this elsewhere.
Edit 2: What I really want to do
This code (https://gist.github.com/0x53A/8848b04c2250364a3c22) goes into the catch-all case and fails with not implemented:parseQuotation:Value (Variable "ax1")
(I expected it to go into | Var(var) ->
) so not only constants known at compile-time, but also function parameters are expanded to their values.
Edit 3:
I ran the working version (https://gist.github.com/0x53A/53f45949db812bde5d97) under the debugger, and it looks like that one is actually the bug:
The quotation is {Call (None, op_Addition, [PropertyGet (None, a, []), Value (1)])}
witha
= Program.a
, so this seems to be a side-effect of the fact that let bindings in modules are compiled into properties. If I am correct, I should maybe file a doc-bug at Microsoft...