F#函数与值

F#函数与值,f#,F#,这是一个非常简单的问题,我只是想检查我所做的以及我如何解释F#是否有意义。如果我有陈述的话 let printRandom = x = MyApplication.getRandom() printfn "%d" x x F#不是将printRandom创建为函数,而是运行它一次,然后为其赋值。现在,当我调用printRandom时,我没有得到一个新的随机值并打印它,而是得到第一次返回的值。我可以绕过这个问题,将其定义为: let printRandom() = x = M

这是一个非常简单的问题,我只是想检查我所做的以及我如何解释F#是否有意义。如果我有陈述的话

let printRandom = 
  x = MyApplication.getRandom()
  printfn "%d" x
  x
F#不是将
printRandom
创建为函数,而是运行它一次,然后为其赋值。现在,当我调用printRandom时,我没有得到一个新的随机值并打印它,而是得到第一次返回的值。我可以绕过这个问题,将其定义为:

let printRandom() = 
  x = MyApplication.getRandom()
  printfn "%d" x
  x

这是区分无参数函数和值的正确方法吗?这对我来说似乎不太理想。它对咖喱、作文等有影响吗

你的分析是正确的

第一个实例定义一个值,而不是一个函数。我承认,当我开始使用F#时,我也有过几次这样的经历。源于C#,包含多个语句的赋值表达式必须是lambda并因此计算延迟,这似乎很自然

F#的情况并非如此。语句几乎可以是任意嵌套的(因为它具有局部范围的函数和值)。一旦你习惯了这一点,你就会开始把它看作是一种优势,因为你可以创建其他函数无法访问的函数和延续


第二种方法是创建逻辑上不带参数的函数的标准方法。不过,我不知道F#团队在这个声明中会使用什么确切的术语(可能是一个函数,它使用的参数类型为
unit
)。因此,我无法评论这对咖喱的影响

正确的观点是F#没有无参数函数。所有函数都必须接受一个参数,但有时您并不关心它是什么,因此使用
()
(类型unit的单例值)。您还可以创建如下函数:

let printRandom unused = 
  x = MyApplication.getRandom()
  printfn "%d" x
  x
或者这个:

let printRandom _ = 
  x = MyApplication.getRandom()
  printfn "%d" x
  x
但是
()
是表示不使用参数的默认方式。它向调用者表达了这个事实,因为类型是
unit->int
而不是
'a->int
;对于读者也是如此,因为调用站点是
printRandom()
而不是
printRandom“unused”

curry和composition实际上依赖于这样一个事实:所有函数都接受一个参数并返回一个值

顺便说一下,使用unit编写调用最常见的方法是使用空格,特别是在F#的非.NET亲属中,如Caml、SML和Haskell。这是因为
()
是一个单例值,而不是像C#中那样的语法

这是画这个的正确方法吗 区分无参数 功能和价值观?这似乎不那么重要 对我来说比理想的多。有吗 在咖喱,构图, 等等

是的,你所描述的是正确的

不管它值多少钱,它有一个非常有趣的结果,能够在声明中部分地计算函数。比较这两种功能:

// val contains  : string -> bool
let contains =
    let people = set ["Juliet"; "Joe"; "Bob"; "Jack"]
    fun person -> people.Contains(person)

// val contains2 : string -> bool
let contains2 person =
    let people = set ["Juliet"; "Joe"; "Bob"; "Jack"]
    people.Contains(person)

这两个函数产生相同的结果,
contains
在声明中创建其人员集并重用它,而
contains2
在每次调用该函数时创建其人员集。最终结果:
包含的
稍微快一点。因此,了解这里的区别可以帮助您更快地编写代码。

看起来像函数体的赋值体让一些程序员感到困惑。通过让赋值返回函数,可以使事情变得更加有趣:

let foo =
    printfn "This runs at startup"
    (fun () -> printfn "This runs every time you call foo ()")

我刚刚在上写了一篇关于它的博文。

Currying在这里并不适用,因为函数只有一个参数,类型为
unit
。部分应用没有意义:要么完全应用该函数(传递
()
),要么根本不调用它。请注意,您几乎肯定希望在第一次出现的
x
之前添加一个
let
——否则您将执行比较,然后丢弃结果。这个问题太棒了,也有同样的问题。不幸的是,我在找到解决方案后发现了这一点。