2

Is it possible to pass data generated locally in F# to the expression that's being compiled in Funscript?

Example of what I mean:

let MyJSFunc str () =
    Globals.alert str

let myStr = File.ReadAllText "somefile.txt"

Compiler.Compiler.Compile(<@ MyJSFunc myStr () @>,noReturn=true)

If I use a static string instead of reading it from a local file it works, so my guess is that Funscript tries to compile the file reading to JS, even though the file has already been read by the time it reaches the compilation?

monoceres
  • 4,722
  • 4
  • 38
  • 63

1 Answers1

3

FunScript attempts to translate the code of all top-level declarations. As you mentioned, this includes thy MyJSFunc function but also the myStr value (which is not possible as it accesses the file system).

One way to solve this is to turn myStr into a local declaration. That way, the F# will store its value in the quotation (rather than storing the definition):

let MyJSFunc str () =
    Globals.alert str

let translate () =
  let myStr = File.ReadAllText "somefile.txt"
  Compiler.Compiler.Compile(<@ MyJSFunc myStr () @>,noReturn=true)

Another way to do the same thing is to use quotation splicing and create a quoted value explicitly using Expr.Value:

open Microsoft.FSharp.Quotations

Compiler.Compiler.Compile(<@ MyJSFunc (%Expr.Value(myStr)) () @>,noReturn=true)
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • I see, that explains it. Do you know the reasoning behind translating all top levels declarations instead of just the declarations contained inside the expression (if that makes sense)? Maybe because types have to declared at the top level? – monoceres Feb 24 '15 at 13:29
  • 2
    This is more of an F# language feature than FunScript feature - all top level bindings are represented as "calls" in quotations while all local values become "embedded values". FunScript simply tries to translate all calls. That said, it would make sense to have some attribute for calls that should be "evaluated" rather than translated. – Tomas Petricek Feb 24 '15 at 13:33
  • I hadn't see this use case but Tomas' solution is very good +1. Adding the attribute to evaluate calls at compile time is also a nice proposal and shouldn't be difficult but I'm afraid users may misuse it thinking some calls can be evaluated at compile time when it's not the case. There would likely be problems too if you use a stand-alone compiler. – Alfonso Garcia-Caro Feb 25 '15 at 03:09