我编写了一个程序,将文件大小从字节转换为F#中的人类可读格式:
let rec sizeFmt num i =
let suffix="B"
let unit = ["";"Ki";"Mi";"Gi";"Ti";"Pi";"Ei";"Zi"]
match abs num with
| x when x < 1024.0 -> printfn "%3.1f %s%s" num unit.[i] suffix
| _ -> sizeFmt (num / 1024.0) (i+1)
let humanReadable n =
sizeFmt (float n) 0
Run Code Online (Sandbox Code Playgroud)
运行示例:
> humanReadable 33;;
33.0 B
val it : unit = ()
> humanReadable 323379443;;
308.4 MiB
val it : unit = ()
>
Run Code Online (Sandbox Code Playgroud)
题:
如果我可以i=0在函数中设置为默认值,那将是很好的
sizeFmt.我检查了F#文档,发现没有默认参数.所以我必须编写一个包装函数
humanReadable.有没有更好的办法?
为了同时处理int和float类型一样输入humanReadable 123;;和humanReadable 123433.33;;,我一定要添加float n在包装功能.显而易见的问题是:它很容易超过最大int尺寸2,147,483,647.我猜可能有更好的方法,有吗?
如果sizeFmt仅使用humanReadable,则使其成为内部函数是有意义的.这避免了"参数默认"问题.
此外,标记外部函数inline会使其接受n支持显式转换的任何类型float.
let inline humanReadable n =
let rec sizeFmt num i =
let suffix="B"
let unit = ["";"Ki";"Mi";"Gi";"Ti";"Pi";"Ei";"Zi"]
match abs num with
| x when x < 1024.0 -> printfn "%3.1f %s%s" num unit.[i] suffix
| _ -> sizeFmt (num / 1024.0) (i+1)
sizeFmt (float n) 0
humanReadable 123 //works
humanReadable 123433.33 //also works
Run Code Online (Sandbox Code Playgroud)
一个可能有帮助的 F# 约定是将主要参数放在参数列表的末尾,将次要参数放在前面 - 与 OO 语言中的约定相反。这可以让您将主要参数传递给函数,例如
let rec sizeFmt i num =
...
123.0 |> sizeFmt 0
Run Code Online (Sandbox Code Playgroud)
它还可以让您轻松创建填充了可选参数的部分函数:
let humanReadable = sizeFmt 0
Run Code Online (Sandbox Code Playgroud)
在回答2时,不,没有更好的方法,除非你使sizeFmt泛型并传入类型值,1024.0但这可能不会使它变得更简单。