Полезные скрипты F # - PullRequest
       12

Полезные скрипты F #

6 голосов
/ 16 февраля 2010

Я изучал использование 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 #, которая может представлять интерес: http://blogs.msdn.com/chrsmith/archive/2008/09/12/scripting-in-f.aspx

Ответы [ 4 ]

6 голосов
/ 16 февраля 2010

Я использую 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)

Теперь я мог легко написать конкретные вызовы для чтения нужных мне данных, преобразовать их в типы данных F #, выполнить некоторую предварительную обработку (при необходимости) и распечатать выходные данные в файл. Например для перерабатывающих компаний у меня было что-то вроде:

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

Генерация вывода в виде последовательности строк также довольно аккуратна, хотя вы, вероятно, могли бы написать более эффективный построитель вычислений, используя StringBuilder.

Другой пример использования F # в интерактивном режиме описан в моей книге функционального программирования в главе 13 (вы можете получить исходный код здесь ). Он подключается к базе данных Всемирного банка (которая содержит много информации о различных странах), извлекает некоторые данные, исследует структуру данных, преобразует их в типы данных F # и вычисляет некоторые результаты (и визуализирует их). Я думаю, что это (один из многих) видов задач, которые можно очень хорошо выполнить в F #.

2 голосов
/ 19 февраля 2010

(альтернативный фрагмент см. Ответ ниже.) Этот фрагмент преобразовывает XML с использованием XSLT. Я не был уверен, что это лучший способ использовать объекты 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))
2 голосов
/ 17 февраля 2010

Иногда, если я хочу получить краткую информацию о структуре 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)

Я уверен, что он может быть оптимизирован / сокращен и будет поощряться другими улучшениями в этом коде. :)

0 голосов
/ 09 марта 2010

После разъяснения подходов к написанию кода F # с существующими классами .net, появился следующий полезный код для преобразования XML-документов с учетом XSL-документов. Функция также позволяет вам создавать пользовательские функции для преобразования XML-документов с помощью конкретного xsl-документа (см. Пример):

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

Это позволяет вам преобразовывать документы следующим образом:

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 ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...