我的第一个F#计划

时间:2009-10-09 03:26:47

标签: f# performance

我们的想法是使用目录中的#of文件创建/填充perfmon计数器。显然,FileNet(程序)使用给定目录作为队列,并且有时会挂起。因此需要监控正在堆叠的文件数量......

现在大多数人可能会在我的“if / then”语句的蜘蛛网上留下你的驴子,但我喜欢写这篇文章,想要变得更好并理解我效率低下的地方。我希望有人会给我一些指示:)

完全工作的源码(我正在使用fsc编译.NET 2.0) http://cl1p.net/fileNetCount

(感谢@Dan向我介绍这种漂亮的非括号语言)

4 个答案:

答案 0 :(得分:2)

这是一个以命令式风格编写的F#程序。这很好,除了你错过了函数式编程的所有优点。

我首先尝试编写简单的内容,例如Fibonnaci序列或计算factorial的程序。使用递归将其写成函数式。

答案 1 :(得分:2)

我的初步印象是,您的应用程序中没有任何内容可以使F#成为一个引人注目的选择。也就是说,以下是一些使用F#功能简化逻辑的方法示例:

// Bring the namespace into scope, like using in C#
open System.Diagnostics

// Methods with descriptive parameter names are good
let Create counter_category counter_name =
    match PerformanceCounterCategory.Exists(counter_category) with
    // Using a guard eliminates a second level of if/then or matching
    | true when PerformanceCounterCategory.CounterExists(counter_name, counter_category)
           -> printfn "Performance counter %A already exists" counter_name
    | true -> printfn "Performance counter category %A already exists" counter_category
    // _ is effectively an "else" clause, or a switch's default
    | _    -> let CounterDatas = new CounterCreationDataCollection()
              let cdCounter1 = new CounterCreationData()
              cdCounter1.CounterName <- counter_name
              cdCounter1.CounterType <- PerformanceCounterType.NumberOfItems64
              CounterDatas.Add(cdCounter1) |> ignore
              printf "Creating category and counter: "
              PerformanceCounterCategory.Create(counter_category, "", PerformanceCounterCategoryType.SingleInstance, CounterDatas) |> ignore
              printfn "Success."

// Fake implementations, left as an exercise
let Scan counter_category counter_name directory =
    printfn "%s %s %s %s" "Scan" counter_category counter_name directory

let Remove counter_category counter_name =
    printfn "%s %s %s" "Remove" counter_category counter_name

// The only place we need to specify a type
let ParseArgs (args : string array) =
    let app = args.[0]
    match args.Length with
    | 1 -> printfn "Usage: %A [create|scan|remove]" app
    // By pairing up the op and number of arguments...
    | n -> match args.[1],n with
           // We can easily handle good cases...
           | "create",4 -> Create args.[2] args.[3]
           | "scan",5   -> Scan args.[2] args.[3] args.[4]
           | "remove",4 -> Remove args.[2] args.[3]
           // And bad cases...
           | "create",_ -> printfn "Usage: %A create <CounterCategory> <CounterName>" app
           | "scan",_   -> printfn "Usage: %A scan <CounterCategory> <CounterName> <Directory>" app
           | "remove",_ -> printfn "Usage: %A remove <CounterCategory> <CounterName>" app
           | op,_       -> printfn "Invalid operation: %A" op

// Sys.argv is just for compatibility
ParseArgs (System.Environment.GetCommandLineArgs())

答案 2 :(得分:0)

您应该尽快将参数分配给某些命名值,这样就可以在不回头查看用法消息的情况下知道它们的含义。

此外,您应该将其分解为方法。检查“创建”,“扫描”或“删除”输入是否正常的逻辑应该采用3种不同的方法。同样,主代码本身也应该有方法。这样,在查看最初执行的代码时,程序的整体逻辑一目了然。

这些建议不一定是功能性的,但它们肯定会使代码更具可读性和意义。

答案 3 :(得分:0)

你正在做很多条件逻辑。尝试使用一些匹配语句。它不一定具有功能性,但它会提高可读性并引导您朝着正确的方向前进。

Adventures in F# - F# 101 Part 5 (Pattern Matching)
Match Expressions (F#) MSDN