有用的F#脚本

有用的F#脚本,f#,scripting,F#,Scripting,我一直在研究F#在开发中的使用,发现(在我的情况下)构建脚本来帮助我简化一些复杂的任务是我可以从中获得价值的地方(目前) 我最常见的复杂任务是为许多任务连接文件(大部分与SQL相关) 我经常这样做,每次我都试图改进我的F#脚本来做到这一点 这是我迄今为止最大的努力: open System.IO let path = "C:\\FSharp\\" let pattern = "*.txt" let out_path = path + "concat.out" File.Delete(out_

我一直在研究F#在开发中的使用,发现(在我的情况下)构建脚本来帮助我简化一些复杂的任务是我可以从中获得价值的地方(目前)

我最常见的复杂任务是为许多任务连接文件(大部分与SQL相关)

我经常这样做,每次我都试图改进我的F#脚本来做到这一点

这是我迄今为止最大的努力:

open System.IO

let path = "C:\\FSharp\\"
let pattern = "*.txt"
let out_path = path + "concat.out"

File.Delete(out_path)
Directory.GetFiles(path, pattern)
 |> Array.collect (fun file -> File.ReadAllLines(file))
 |> (fun content -> File.WriteAllLines(out_path, content) )
我相信其他人也有脚本,可以让他们有时复杂/无聊的任务变得更容易。 您使用了哪些F#脚本来执行此操作,或者您发现F#脚本有哪些其他用途

我发现提高我的F#的最好方法是浏览其他脚本,了解如何应对特定情况。希望这个问题将来能对我和其他人有所帮助。:)

我发现了一篇关于生成F#脚本的文章,可能很感兴趣:

当我需要快速预处理某些数据或在各种格式之间转换数据时,我以类似的方式使用F。F#有一个很大的优势,就是可以创建高阶函数来执行各种类似的任务

例如,我需要从SQL数据库加载一些数据,并生成加载数据的Matlab脚本文件。我需要对几个不同的SQL查询执行此操作,因此我编写了以下两个函数:

// Runs the specified query 'str' and reads results using 'f'
let query str f = seq { 
  let conn = new SqlConnection("<conn.str>");
  let cmd = new SqlCommand(str, conn)
  conn.Open()
  use rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
  while rdr.Read() do yield f(rdr) } 

// Simple function to save all data to the specified file
let save file data = 
  File.WriteAllLines(@"C:\...\" + file, data |> Array.ofSeq)
以字符串序列的形式生成输出也非常简洁,不过您可以使用
StringBuilder
编写更高效的计算生成器


以交互方式使用F#的另一个示例在第13章的我的文章中介绍(您可以)。它连接到世界银行数据库(其中包含许多关于各个国家的信息),提取一些数据,探索数据的结构,将它们转换为F#数据类型,并计算一些结果(并将其可视化)。我认为这是在F#中可以很好地完成的(许多)任务之一。

有时,如果我想简要了解XML结构(或有一个递归列表用于其他形式,如搜索),我可以使用以下脚本打印XML中的节点选项卡列表:

open System
open System.Xml

let path = "C:\\XML\\"
let xml_file = path + "Test.xml"

let print_element level (node:XmlNode) = [ for tabs in 1..level -> "   " ] @ [node.Name]
                                            |> (String.concat "" >> printfn "%s")

let rec print_tree level (element:XmlNode) = 
        element 
        |> print_element level
        |> (fun _ -> [ for child in element.ChildNodes -> print_tree (level+1) child ])
        |> ignore

new XmlDocument()
 |> (fun doc -> doc.Load(xml_file); doc)
 |> (fun doc -> print_tree 0 doc.DocumentElement)
我相信它可以被优化/减少,并会受到其他人对该代码的改进的鼓励。:)

(有关其他代码片段,请参见下面的答案。) 此代码段使用XSLT转换XML。我不确定使用XslCompiledTransform和XmlDocument对象的最佳方法是否是F#中最好的方法,但它似乎很管用。我相信有更好的方法,我很高兴听到他们

(* Transforms an XML document given an XSLT. *)

open System.IO
open System.Text
open System.Xml
open System.Xml.Xsl

let path = "C:\\XSL\\"

let file_xml = path + "test.xml"
let file_xsl = path + "xml-to-xhtml.xsl"

(* Compile XSL file to allow transforms *)
let compile_xsl (xsl_file:string) = new XslCompiledTransform() |> (fun compiled -> compiled.Load(xsl_file); compiled)
let load_xml (xml_file:string) = new XmlDocument() |> (fun doc -> doc.Load(xml_file); doc)

(* Transform an Xml document given an XSL (compiled *)
let transform (xsl_file:string) (xml_file:string) = 
      new MemoryStream()
        |> (fun mem -> (compile_xsl xsl_file).Transform((load_xml xml_file), new XmlTextWriter(mem, Encoding.UTF8)); mem)
        |> (fun mem -> mem.Position <- (int64)0; mem.ToArray())

(* Return an Xml fo document that has been transformed *)
transform file_xsl file_xml
    |> (fun bytes -> File.WriteAllBytes(path + "out.html", bytes))
(*转换给定XSLT的XML文档。*)
开放系统
开放系统.Text
开放系统.Xml
open System.Xml.Xsl
let path=“C:\\XSL\\”
让文件_xml=path+“test.xml”
让file_xsl=path+“xml到xhtml.xsl”
(*编译XSL文件以允许转换*)
让compile_xsl(xsl_文件:string)=新建xslcileddentransform()|>(fun compiled->compiled.Load(xsl_文件);compiled)
让load_xml(xml_文件:string)=新建XmlDocument()|>(fun doc->doc.load(xml_文件);doc)
(*在给定XSL的情况下转换Xml文档(已编译*)
let transform(xsl_文件:字符串)(xml_文件:字符串)=
新内存流()
|>(fun mem->(compile_xsl xsl_file).Transform((load_xml_file),新的XmlTextWriter(mem,Encoding.UTF8));mem)
|>(fun mem->mem.Position(fun字节->File.writealBytes(路径+“out.html”,字节))

在阐明了使用现有.net类编写F#代码的方法之后,出现了以下有用的代码,用于转换给定xsl文档的xml文档。该函数还允许您创建自定义函数,以使用特定xsl文档转换xml文档(参见示例):

这允许您通过以下方式转换文档:

let result = transform "report.xml" "report.xsl"
或者,您可以创建另一个可多次使用的函数:

let transform_report "report.xsl"

let reports = [| "report1.xml"; "report2.xml" |]
let results = [ for report in reports do transform_report report ]

我想您可能会发现PowerShell是一个比F#更好的脚本工具。它也使用.NET对象。Chris Smith(来自链接中的文章)对此观点有一个有趣的回应:“唯一比学习一种新的编程语言和一种新的shell语言更好的工具,就是学习一种新的编程语言。”你说的只是sys-admin风格的脚本,或者更普遍的有用的代码片段?这里有一些:谢谢你的想法。SQL脚本听起来像是函数式编程的一个很好的用途:)
let result = transform "report.xml" "report.xsl"
let transform_report "report.xsl"

let reports = [| "report1.xml"; "report2.xml" |]
let results = [ for report in reports do transform_report report ]