我以FSharp.Charting探索F#,我以为我会从一个简单的“hello world”开始,但这给我留下了更多的问题,而不是代码行。

#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)

这在VS的交互式窗口中有效,但是我要做的是从cmd行执行此脚本(使用fsi.exe)。我将fsx文件与fsi建立了关联,但是当我执行它时,它会打开fsi,但不会创建图表。我需要做什么?

最佳答案

简短回答:在程序末尾添加以下行:

System.Windows.Forms.Application.Run()

长答案:

确实创建了图表,但是它立即消失了,因为您的程序在创建图表后立即退出。在Visual Studio的F#交互式窗口中不会发生这种情况,因为F#交互式窗口在执行程序后不会立即关闭-它只是挂在那儿,等待您提交更多代码以执行。

为了使您的程序不会立即退出,您可以实现一些等待机制,例如等待设置的时间(请参阅System.Threading.Thread.Sleep)或等待用户按Enter(通过stdin.ReadLine())等。

但是,这实际上并不能帮助您,因为存在下一个问题:图表是通过Windows Forms绘制的,它依赖于message loop运行-否则窗口无法接收消息,因此无法进行事件绘制。

FSI does have its own built-in event loop,这就是您的程序在VS下的工作方式。但是,如果您实现了“等待”机制(例如stdin.ReadLine()),则此事件循环将被阻止-无法泵送消息。因此,防止程序退出而不干扰图表窗口功能的唯一明智的方法是启动自己的事件循环。这正是Application.Run()所做的。

保存到磁盘而不显示:

(回应评论)

据我了解,FSharp.Charting库旨在作为一种在屏幕上显示图表的快捷方法,主要用例是探索F#Interactive中的实时数据集。更具体地说,Chart对象的某些关键属性(例如 ChartAreas Series )在图表创建时不会初始化,而是仅在屏幕上显示时才初始化(请参见source code),并且没有这些属性,图表将保持空白。

除了向库提交请求请求外,我建议下拉至底层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)

关于f# - 如何在fsi中运行.fsx,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43968308/

10-10 23:59