【问题标题】:How to avoid changing parameter order如何避免更改参数顺序
【发布时间】:2016-08-11 01:22:43
【问题描述】:

我目前正在做一些来自exercism.io 的练习。其中一项练习是将序列中的所有数字相加,这些数字是来自不同序列的一个或多个数字的倍数。将问题拆分为更小的函数似乎是个好主意,我想出了这个:

let multipleOf m n =
    n % m = 0

let anyMultipleOf (m: int list) n =
    m
    |> Seq.exists (multipleOf n)

let sumOfMultiples m n =
    [1..n-1]
    |> Seq.filter (anyMultipleOf m)
    |> Seq.sum

我的想法是,我可以使用部分应用程序将m 参数“烘焙”到我的(any)multipleOf 函数中。但是这段代码并没有按照我想要的方式工作,因为Seq.exists (multipleOf n) 实际上将n 应用为我的m 参数。

如何在不必颠倒multipleOf 函数的参数顺序的情况下重构此代码?


注意:我想要一个在我的 anyMultipleOf 函数中使用我的 multipleOf 函数的解决方案。此解决方案有效,但不重用我的第一个功能:

let anyMultipleOf (m: int list) n =
    m
    |> Seq.exists (fun x -> n % x = 0)

【问题讨论】:

  • multipleOfanyMultipleOf 都应该真正具有相反顺序的参数。参数的定义从更一般到更具体。重用 (any)MultipleOf x 比目前的方式更有意义
  • 我的思维过程正好相反。就像检查我对部分应用序列的任何值一样:let anyMultipleOfMyNumbers = anyMultipleOf [3;5;7]
  • 这个也很好用:let filterMultiplesOf5 numlist = numlist |> Seq.filter (multipleOf 5)

标签: f#


【解决方案1】:

确实输入了使用flip的建议,但显而易见的做法是:

let anyMultipleOf (m: int list) n =
    m
    |> Seq.exists (fun x -> multipleOf x n)

flip 是一个不错的工具,但翻转函数的管道读起来很痛苦。

【讨论】:

  • 虽然它和翻转一样,但我更喜欢你的解决方案。参数的去向更明确,而且参数更多时也更容易阅读。
【解决方案2】:

虽然我不清楚您为什么不重新定义 anyMultipleOf 以将列表作为最后一个参数,但您始终可以使用 flip

let flip f x y = f y x

这个函数exists in Haskell,但不在 FSharp.Core 中,这就是你必须自己定义它的原因。

例如,flip anyMultipleOf 返回一个类型为 int -> int list -> bool 的函数,如果我正确理解问题,这就是您想要的。

【讨论】:

    【解决方案3】:

    您可以为自己定义一个功能来做到这一点:
    以相反的顺序获取一个函数和 2 个参数,并将以正确顺序应用参数的结果返回给函数

    let flip f y x = f x y
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-04
      • 2015-03-28
      • 2020-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多