Search code examples
f#f#-dataliterate-programmingf#-scripting

F# Literate pass arguments to script file


I am using F# Formatting to do some Literate programming.

My use case is that I have a couple of hundred data sets that I need to run through, and for each I want to create a "report" of some statistics and plots. They are all of the same format.

So what I want is to just have one fsx script file with F# code and markdown, that can be parsed in a loop to generate separate html files.

My current code looks like this:

// Create FSI evaluator with transformation enabling charts to show.
let fsiEval = FsiEvaluator() 
fsiEval.RegisterTransformation(transformation)
let source = __SOURCE_DIRECTORY__
let template = Path.Combine(source, "zeros.html")
let script = Path.Combine(source, "zeros.fsx")
Literate.ProcessScriptFile(script, templateFile = template, fsiEvaluator = fsiEval, output = "rendered.html")

This works fine, but I have to hard code which dataset I am looking at in the "zeros.fsx" file. I would like to pass parameters into this method:

Literate.ProcessScriptFile(script, templateFile = template, fsiEvaluator = fsiEval, output = "rendered.html")

so I can loop over it and generate all my different reports. But I can't find in the documentation how to do that.


Solution

  • You can run arbitrary F# code using the fsiEval object before it runs the script, so one way to do this would be to write some code that defines a global variable, which will then be visible from the scripts (although, you will get an error in F# editor when editing the script...). Code to do this:

    let fsiEval = FsiEvaluator() 
    let ifsi = fsiEval :> IFsiEvaluator
    ifsi.Evaluate("let magic = 40", false, None)
    

    And my test file now shows the result as 42:

    let res = 2 + magic
    (*** include-value: res ***)
    

    This works for configuration that you can reasonably pass via source code - I'm not sure if there is a good way of passing more complex objects around to the script.