How to run .fsx in fsi
Learning F # with FSharp.Charting I thought I'd start with a simple hello world, but that leaves me with more questions than lines of code.
#load @"..\packages\FSharp.Charting.0.90.14\FSharp.Charting.fsx"
open FSharp.Charting
let chart = Chart.Line([ for x in 0 .. 10 -> x, x*x ])
chart.ShowChart()
chart.SaveChartAs(@"C:\Temp\chart.png",ChartTypes.ChartImageFormat.Png)
This works in an interactive window in VS, but I want to do this script from the cmd line (using fsi.exe). I linked to fsx files in fsi, but when I executed it, it opens fsi, but no diagram is generated. What do I need to do?
source to share
Short answer : add the following line at the end of your program:
System.Windows.Forms.Application.Run()
Long answer:
The diagram is created, but it disappears immediately because your program exits immediately, right after the diagram is created. This does not happen in the F # Interactive window in Visual Studio, because the F # interactive window does not close immediately after your program runs - it just hangs there, waiting for you to submit more code to execute.
To prevent your program from exiting immediately, you could implement some kind of wait mechanism, for example, wait for a set amount of time (see System.Threading.Thread.Sleep
) or wait for the user to press Enter (through stdin.ReadLine()
), etc.
However, this will not help you because there is the following problem: the diagram is drawn through Windows Forms, which relies on a running message loop - otherwise the window cannot receive messages and therefore cannot draw the event itself.
FSI has its own built-in event loop and this is how your program works under VS. However, if you implement a wait mechanism (for example stdin.ReadLine()
), this event loop will block - no messages can be passed. Thus, the only sane way to keep your program from exiting without interfering with the functioning of the diagram window is to start your own event loop. And that's exactly what it does Application.Run()
.
Saving to disk without display:
(in response to comment)
From what I understand, the library FSharp.Charting
was intended as a quick and dirty way of displaying graphs on the screen, the main use case of which is explored in datasets inside F # Interactive. In particular, some key object properties Chart
, such as ChartAreas
and are Series
not initialized when the diagram is created, but only when they are displayed on the screen (see the source code ), and without these properties the diagram remains empty.
Aside from submitting a pull request to the library, I recommend dropping the base one System.Windows.Forms.DataVisualization.Charting.Chart
:
open System.Windows.Forms.DataVisualization.Charting
let ch = new Chart()
ch.ChartAreas.Add( new ChartArea() )
let s = new Series( ChartType = SeriesChartType.Line )
s.Points.DataBind( [for x in 1..10 -> x, x*x], "Item1", "Item2", "" )
ch.Series.Add s;
ch.SaveImage(@"C:\Temp\chart.png", System.Drawing.Imaging.ImageFormat.Png)
source to share