我有这段代码应该生成随机名称:
let generateName =
let rnd = System.Random()
let c1 = rnd.Next(65, 90) |> System.Convert.ToChar |> string
let c2 = rnd.Next(65, 90) |> System.Convert.ToChar |> string
let n = rnd.Next(0, 999) |> string
c1 + c2 + n
Run Code Online (Sandbox Code Playgroud)
这会计算为一个字符串,这不是我想要的.添加unit-Parameter修复了问题,但现在我必须像C#函数一样调用我的函数:
let myFunc() =
"Hello"
myFunc()
Run Code Online (Sandbox Code Playgroud)
这是我必须这样做,还是有更惯用的方式?
TL; DR: ()在这方面有一个完全不同的意义,比它在C#,所以不要格式化相同的方式,在C#中-使用let myFunc () =和myFunc ()替代,更好地反映实际的语义,将反过来澄清你如何看待和理解代码.
在C#中,()表示一组空参数(用于函数/构造函数定义)或参数(用于函数/构造函数调用站点); 即,它定义或调用一个nullary函数.在F#中,()是一个类型的文字unit,类似于42文字的类型int; 即,它本身[]就是一个值,就像空列表的值一样.这种差异有很多不足之处.
在F#中,当你定义一个let仅()用于参数的函数时let myFunc() =,你实际上是使用模式匹配语法来定义一个带有类型参数的一元函数unit(不是一个无效的函数!).这种特殊的模式匹配实例被认为是理所当然的,许多人并没有意识到它首先是模式匹配; 但是,事实上,定义一个函数let myFunc () =而不是let myFunc (_:unit) =类似于let myFunc [] =而不是let myFunc (x:'a list) =(并且随后声明它x是空的).
而在F#中,当你调用一个let函数时(),就像在中myFunc (),你没有表示'没有参数'; 你实际上是在提供一个类型的参数unit,它的奇异值经常被使用,它有自己的文字语法:().
说服自己unit与'无参数/参数'不同,实际上只是另一个参数/参数,考虑以下事实是完全合法的:
let myFunc() (i:int) (_:unit*unit) = i
let n = myFunc() 42((),())
printfn "%d" n
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,给予unit特殊的空白处理是愚蠢的,因为它并不特别.; - ]
总而言之,由于通常(必要?)用空格分隔任何命名参数/参数,因此它是惯用的以保持一致并对符号模式/值执行相同操作:
let myFunc () =
"Hello"
myFunc ()
Run Code Online (Sandbox Code Playgroud)
这正是它的工作原理.没有"有用"参数的函数需要有一个unit参数来实际使其成为一个函数.
将函数名称和()空格分开以使其看起来更少的方法和更多的函数y 并不罕见,但这纯粹是装饰性的.