【问题标题】:How to rewrite this function using the pipeline operator如何使用管道运算符重写此函数
【发布时间】:2023-04-01 05:02:01
【问题描述】:

这些是函数定义。

func1: 'a -> unit
func2: 'b -> 'a
func3: string -> 'b list    

当前函数

let f =  Seq.iter((fun a -> func1(func2 a)) func3(s) 

据我所知

let f =  func3(s) 
           |> ((fun a -> func2 a 
                         |> func1) 
           |> Seq.iter)

我觉得应该可以松开 lambda 和括号。

【问题讨论】:

    标签: f#


    【解决方案1】:

    你可以不用管道,很简单

    Seq.iter (func1 << func2) << func3
    

    (这是一个带有一些参数的函数 [与func3 相同] 和与Seq.iter 相同的输出)。

    你可以测试一下

    let func1 x = printfn "Number: %d" x
    
    let func2 (a, b) = a + b
    
    let func3 = Seq.map (fun n -> (n, 2 * n))
    
    let f : (seq<_> -> unit) = Seq.iter (func1 << func2) << func3
    
    f [1..5]
    

    有输出

    Number: 3
    Number: 6
    Number: 9
    Number: 12
    Number: 15
    
    val func1 : x:int -> unit
    val func2 : a:int * b:int -> int
    val func3 : (seq<int> -> seq<int * int>)
    val f : (seq<int> -> unit)
    val it : unit = ()
    

    :)

    【讨论】:

      【解决方案2】:

      可以使用函数组合运算符&gt;&gt;:

      func3() |&gt; Seq.iter (func2 &gt;&gt; func1)

      【讨论】:

        【解决方案3】:

        我认为问题是,为什么要使用管道运算符?

        我发现您的原始代码非常易读。您不应该仅仅为了使用它们而尝试使用管道运算符(或函数组合)。现在,在您的代码中,输入 s 出现在末尾,这有点令人遗憾(您看不到代码的主要输入是什么)。我可能会将其重写为(另外,s 并不是一个真正的描述性名称):

        s |> func3 
          |> Seq.iter (fun a -> func1 (func2 a))
        

        您也可以使用函数组合 - 但我不经常使用它,因为它不(总是)有助于提高可读性。但是在Seq.iter的参数中使用它可能是相当合理的。

        在完全不相关的注释中,您可以使用for 循环并编写:

        for a in func3 s do
          func1 (func2 a)
        

        我实际上发现这比这里的任何其他版本的代码都更具可读性(如果 F# 为您提供了一种用于迭代序列的语言功能,而这正是您所需要的,为什么不使用它?)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-06-07
          • 2021-11-16
          • 2021-05-03
          • 1970-01-01
          • 2015-03-12
          相关资源
          最近更新 更多