2010-02-16 14 views
6

He estado investigando el uso de F # para el desarrollo y he encontrado (para mi situación) la construcción de guiones que me ayuden a simplificar algunas tareas complejas es donde puedo obtener valor (en este momento).Útiles guiones F #

Mi tarea compleja más común es concatenar archivos para muchas tareas (principalmente relacionadas con SQL).

Hago esto a menudo y cada vez trato de mejorar mi script F # para hacer esto.

Este es mi mejor esfuerzo hasta el momento:

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

estoy seguro de que otros tienen las secuencias de comandos que hace sus tareas complejas veces/aburrida más fácil. ¿Qué scripts F # has utilizado para hacer esto o qué otros propósitos para los scripts F # has encontrado útiles?

Encontré que la mejor manera de mejorar mi F # era buscar otros scripts para obtener ideas sobre cómo abordar situaciones específicas. Espero que esta pregunta nos ayude a mí y a otros en el futuro. :)

he encontrado un artículo en la generación F # scripts que pueden ser de interés: http://blogs.msdn.com/chrsmith/archive/2008/09/12/scripting-in-f.aspx

+0

Creo que es posible que PowerShell sea una herramienta mejor que F # para las secuencias de comandos. También usa objetos .NET. –

+6

Chris Smith (del artículo en el enlace), tiene una respuesta interesante a ese argumento: "lo único mejor que aprender un nuevo lenguaje de programación Y un nuevo lenguaje de shell, es simplemente aprender un nuevo lenguaje de programación". – Russell

+0

¿Estás hablando de scripts de estilo sys-admin o, en general, de fragmentos de código útiles? Algunos aquí: http://stackoverflow.com/questions/833180/handy-f-snippets – Benjol

Respuesta

6

utilizo F # de forma similar cuando necesito rápidamente pre-proceso de algunos datos o convertir datos entre varios formatos . F # tiene una gran ventaja de que puede crear funciones de orden superior para realizar todo tipo de tareas similares.

Por ejemplo, necesitaba cargar algunos datos de la base de datos SQL y generar archivos de script de Matlab que cargan los datos. Que tenía que hacer esto por un par de diferentes consultas SQL, así que escribí estas dos funciones:

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

Ahora podría escribir fácilmente llamadas específicas para leer los datos que necesito, convertirlos a tipos # de datos F, hace algunos preprocesamiento (si es necesario) e imprima las salidas en un archivo. Por ejemplo, para las empresas de transformación que tenía algo así como:

let comps = 
    query "SELECT [ID], [Name] FROM [Companies] ORDER BY [ID]" 
     (fun rdr -> rdr.GetString(1)) 
let cdata = 
    seq { yield "function res = companies()" 
     yield " res = {" 
     for name in comps do yield sprintf " %s" name 
     yield " };" 
     yield "end" } 
save "companies.m" cdata 

Generación de salida como una secuencia de cadenas también es bastante limpio, aunque probablemente podría escribir un constructor de cómputo más eficiente el uso de StringBuilder.

Otro ejemplo del uso de F # en la forma interactiva se describe en mi functional programming book en el Capítulo 13 (puede get the source code here). Se conecta a la base de datos del Banco Mundial (que contiene mucha información sobre varios países), extrae algunos datos, explora la estructura de los datos, los convierte a tipos de datos F # y calcula algunos resultados (y los visualiza). Creo que este es uno de los muchos tipos de tareas que se pueden realizar muy bien en F #.

+0

Gracias por sus ideas. El scripting SQL suena como un excelente uso para la programación funcional :) – Russell

2

veces si quiero un escrito de una estructura XML (o tener una lista recursiva para utilizar en otras formas, tales como búsquedas), que puede imprimir una lista con pestañas de nodos en el XML utilizando el siguiente script:

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) 

Estoy seguro de que se puede optimizar/reducir y alentaría las mejoras de otros en este código. :)

2

(Para obtener un fragmento alternativo, consulte la respuesta a continuación.) Este fragmento transforma un XML utilizando un XSLT. No estaba seguro de la mejor manera de usar los objetos XslCompiledTransform y XmlDocument de la mejor manera en F #, pero parecía funcionar.Estoy seguro de que hay mejores maneras y me gustaría saber de ellas.

(* 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)) 
0

Tras aclarar enfoques para escribir F # código con clases .NET existentes, el siguiente código útil acercó para transformar documentos XML en cuestión documentos XSL. La función también le permite crear una función personalizada para transformar documentos XML con un documento XSL específico (ver ejemplo):

let transform = 
    (fun xsl -> 
     let xsl_doc = new XslCompiledTransform() 
     xsl_doc.Load(string xsl) 

     (fun xml -> 
      let doc = new XmlDocument() 
      doc.Load(string xml) 
      let mem = new MemoryStream() 
      xsl_doc.Transform(doc.CreateNavigator(), null, mem) 
      mem 
     ) 
    ) 

Esto le permite transformar documentos de esta manera:

let result = transform "report.xml" "report.xsl" 

o usted puede crear otra función que se puede usar varias veces:

let transform_report "report.xsl" 

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