强制让我们绑定到函数而不是值

Luc*_*ier 5 f#

我有这段代码应该生成随机名称:

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)

这是我必须这样做,还是有更惯用的方式?

ild*_*arn 6

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)

  • "惯用语"可能是一个强有力的词.例如,FSharp.Core源不使用此样式.https://github.com/fsharp/fsharp/tree/master/src/fsharp/FSharp.Core.我个人在风格之间来回跳跃,结果是非空间变体.虽然`unit`是一个arg,但我发现它有一个特殊的含义 - "运行这个函数". (2认同)

Tea*_*Dev 5

这正是它的工作原理.没有"有用"参数的函数需要有一个unit参数来实际使其成为一个函数.

将函数名称和()空格分开以使其看起来更少的方法和更多的函数y 并不罕见,但这纯粹是装饰性的.


kem*_*002 5

不,这就是F#的工作方式.F#中的每个函数都必须有一个参数(带有多个参数的函数被分成多个函数,一个参数返回一个中间函数),每个函数都必须返回一些东西,即使它是单位.