【问题标题】:F# - Function with no arguments?F# - 没有参数的函数?
【发布时间】:2017-08-28 23:23:37
【问题描述】:

以函数式思维方式思考时,鉴于函数应该是纯函数,因此可以得出结论,任何没有参数的函数基本上只是一个值。
然而,现实阻碍了它,并且使用不同的输入,我可能不需要某个函数,如果该函数的计算量很大,如果不需要,我不想评估它。
我找到了一种解决方法,使用 let func _ = ... 并使用 func 1 或其他方式调用它,但这对读者来说感觉非常不习惯且令人困惑。

这归结为一个问题:在 F# 中,是否有一种适当的方法来声明一个具有零参数的函数,而无需在声明时对其进行评估?

【问题讨论】:

  • 人们也可能会认为值是“基本上没有参数的函数”,这就是 Haskell 看待事物的方式。我想知道为什么 F# 在这方面有所不同。
  • @self 这是因为 Haskell 默认也是惰性的;除非程序员明确要求,否则不会在声明时评估任何值,包括函数。 F# 中的语义默认是严格的,应该以不同的方式表示。
  • 在 Haskell 中,纯函数实际上是纯函数。 F# 中“现实阻碍”的唯一原因是 F# 函数不能保证是纯函数。任何东西是否懒惰都没有关系。在 Haskell 中,无参数函数只能返回一个值。 @jpaugh
  • 我应该补充一点,Haskell 中的所有函数都是纯函数。我之前的评论听起来像是有纯函数和非纯函数。一切都是纯净的。

标签: f# functional-programming unit-type


【解决方案1】:

通常的习惯用法是将函数定义为接受一个 Unit 类型的参数 (let functionName () = 42)。然后它将被称为functionName ()。 (单位类型只有一个值,()。)

【讨论】:

  • hmm 但是您不能使用这种语法初始化记录类型(例如 type Getter = {Name: string; Function: () -> string;} 是不允许的)。知道如何解决这个问题吗?
  • 感谢您的回复,但无法编译。这样的记录类型可以写吗?
  • @evolvedmicrobe 对于我来说,unit 编译得很好。
  • Joel Mueller's answer 以更好的方式解决了问题的两个要点:任何没有参数的函数基本上只是一个值我喜欢lazy() 很好地解决了这两个问题
  • @Oliver,实际上,使用lazy() 将具有不同的内存/性能特征,并且可能并不总是正确的解决方案。 This post(以及该页面上的其他人)更详细地介绍。
【解决方案2】:

我想你想要的是lazy

let resource = 
    lazy(
        // expensive value init here
    )

然后当你需要读取值时......

resource.Value

如果您从不调用 Value 属性,lazy 块内的代码将永远不会运行,但如果您调用它,该代码将不会运行超过一次。

【讨论】:

  • 此建议的缺点是调用resource.Value 将始终返回相同的值,因为它只执行一次,而“无参数”函数的返回值可能因每次调用而异。跨度>
  • 是的,但是如果函数是纯函数并且没有参数,那么无论如何它总是会返回相同的值。
  • 一个函数是“纯”的,如果给定相同的输入,它总是产生相同的输出。我并没有声称所有方法都适用于惰性工作,或者甚至认为不纯函数在某些方面是不好的。只是澄清哪类函数惰性是合适的。
  • 现在我明白了。感谢您花时间解释这些事情 - 我已经重新阅读了这个问题,您的解决方案实际上正是 OP 所追求的 :-)
  • 随机数生成器函数也存在于纯语言中。请记住,随机数(不使用 io)是伪随机的,随机数的每次迭代都需要一个种子来创建新值和新种子,保存种子并返回随机值。在纯语言中,您可以取回种子和值,并将种子传递给对生成器的下一次调用。重新播种生成器是一个 io 操作。 Haskell 使用 monad 来完成此操作,因此您实际上不必像那样传递种子,但这就是语法糖下实际发生的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多