我的第一个F#程序 [英] My First F# program

查看:58
本文介绍了我的第一个F#程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚写完我的第一个F#程序.在功能方面,代码按我想要的方式工作,但不确定代码是否有效.如果有人可以为我审查代码并指出可以改进代码的地方,我将不胜感激.

I just finish writing my first F# program. Functionality wise the code works the way I wanted, but not sure if the code is efficient. I would much appreciate if someone could review the code for me and point out the areas where the code can be improved.

谢谢 苏达利

open System
open System.IO
open System.IO.Pipes
open System.Text
open System.Collections.Generic
open System.Runtime.Serialization


[<DataContract>] 
type Quote = { 
    [<field: DataMember(Name="securityIdentifier") >] 
    RicCode:string
    [<field: DataMember(Name="madeOn") >] 
    MadeOn:DateTime
    [<field: DataMember(Name="closePrice") >] 
    Price:float 
    }

let m_cache = new Dictionary<string, Quote>() 

let ParseQuoteString (quoteString:string) = 
    let data = Encoding.Unicode.GetBytes(quoteString)
    let stream = new MemoryStream() 
    stream.Write(data, 0, data.Length); 
    stream.Position <- 0L 
    let ser = Json.DataContractJsonSerializer(typeof<Quote array>) 
    let results:Quote array = ser.ReadObject(stream) :?> Quote array
    results

let RefreshCache quoteList =
    m_cache.Clear()
    quoteList |> Array.iter(fun result->m_cache.Add(result.RicCode, result))


let EstablishConnection() =
    let pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut, 4)
    let mutable sr = null
    printfn "[F#] NamedPipeServerStream thread created, Wait for a client to connect"
    pipeServer.WaitForConnection()
    printfn "[F#] Client connected."
    try
        // Stream for the request. 
        sr <- new StreamReader(pipeServer)
    with
    | _ as e -> printfn "[F#]ERROR: %s" e.Message
    sr


while true do
    let sr = EstablishConnection()
    // Read request from the stream.
    printfn "[F#] Ready to Receive data"

    sr.ReadLine()  
    |>  ParseQuoteString  
    |>  RefreshCache

    printfn "[F#]Quot Size, %d" m_cache.Count
    let quot = m_cache.["MSFT.OQ"]
    printfn "[F#]RIC: %s" quot.RicCode
    printfn "[F#]MadeOn: %s" (String.Format("{0:T}",quot.MadeOn))
    printfn "[F#]Price: %f" quot.Price

推荐答案

通常,您应该尝试使用不可变的数据类型,并避免使用诸如全局变量和命令式循环之类的命令式构造-尽管在许多情况下,在F#中使用它们就可以了,仅在有充分理由的情况下才应使用它们.这里有几个可以使用功能方法的示例:

In general, you should try using immutable data types and avoid imperative constructs such as global variables and imperative loops - although using them in F# is fine in many cases, they should be used only when there is a good reason for doing so. Here are a couple of examples where you could use functional approach:

首先,要使代码更具功能性,应避免使用全局可变缓存.相反,您的RefreshCache函数应该返回数据作为结果(最好使用某些函数数据结构,例如F#Map类型):

First of all, to make the code more functional, you should avoid using global mutable cache. Instead, your RefreshCache function should return the data as the result (preferably using some functional data structure, such as F# Map type):

let PopulateCache quoteList = 
  quoteList 
  // Generate a sequence of tuples containing key and value 
  |> Seq.map (fun result -> result.RicCode, result)
  // Turn the sequence into an F# immutable map (replacement for hashtable)
  |> Map.ofSeq

使用它的代码将像这样更改:

The code that uses it would be changed like this:

let cache = 
  sr.ReadLine()   
  |>  ParseQuoteString   
  |>  PopulateCache

printfn "[F#]Quot Size, %d" m_cache.Count 
let quot = m_cache.["MSFT.OQ"] 
// The rest of the sample stays the same


EstablishConnection函数中,您绝对不需要声明可变变量sr,因为在发生异常的情况下,该函数将返回null.我会改用option类型来确保这种情况得到处理:


In the EstablishConnection function, you definitely don't need to declare a mutable variable sr, because in case of an exception, the function will return null. I would instead use option type to make sure that this case is handled:

let EstablishConnection() = 
    let pipeServer = 
      new NamedPipeServerStream("testpipe", PipeDirection.InOut, 4) 
    printfn "[F#] NamedPipeServerStream thread created..." 
    pipeServer.WaitForConnection() 
    printfn "[F#] Client connected." 
    try // Wrap the result in 'Some' to denote success
        Some(new StreamReader(pipeServer))
    with e -> 
        printfn "[F#]ERROR: %s" e.Message 
        // Return 'None' to denote a failure
        None 

可以使用递归函数编写主循环,该递归函数在EstablishConnection失败时停止:

The main loop can be written using a recursive function that stops when EstablishConnection fails:

let rec loop() =
  match EstablishConnection() with
  | Some(conn) ->
      printfn "[F#] Ready to Receive data"
      // rest of the code
      loop() // continue looping
  | _ -> () // Quit

这篇关于我的第一个F#程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆