【问题标题】:make printfn more clear in a function pipeline使 printfn 在函数管道中更清晰
【发布时间】:2016-11-23 14:11:38
【问题描述】:

所以我把最后一块放在管道里

|> Array.iter (fun name -> name 
                                |> transform 
                                |> printfn "RENAME '%s' INTO '%s'" name )

变换是:

let transform (text: string) = 
    text.Replace(" ", ".")

对我来说iter 谓词函数不是很清楚,它是说将名称推入transform 然后将结果推入printfn 并附加原始名称......

有没有办法使用管道向前或向后操作符使转换管道更能揭示意图。

我想也许

name
  |> printfn "RENAME '%S' INTO '%S'"
  <| transform

但显然这行不通。

如果它不能在管道中看起来更好,那么我想这是最简洁的方法 - 除了创建一个新函数以某种方式将 printfn 与转换结合起来,但我不介意避免这种情况.. .

我只是想确保我没有遗漏任何简单的语法..

我认为没有,因为我面临一个需要多个参数的函数,为了在管道中使用它,它只能有 1 个参数,这实际上是我通过部分应用程序所做的.

【问题讨论】:

    标签: f#


    【解决方案1】:

    有时最好避免不必要的管道,因为它会混淆代码。 您的函数仅打印如下:

    printfn "RENAME '%s' INTO '%s'" name (transform name)
    

    你可以使用&lt;|省略括号:

    printfn "RENAME '%s' INTO '%s'" name <| transform name
    

    恕我直言,这看起来更好。

    【讨论】:

    • 那么最后一个表达式是否会出现在Array.iter 的旁边
    • Array.iter (fun name -&gt; 和身体,是的
    【解决方案2】:

    也许在这种情况下跳过管道更清楚?

    |> Array.iter (fun name -> printfn "RENAME '%s' INTO '%s'" name (transform name))
    

    另请注意,您的原始谓词可以像这样进一步组合:

    |> Array.iter (transform >> printfn "RENAME '%s' INTO '%s'" name)
    

    如果您希望变换最后出现,可以这样写:

    |> Array.iter ((printfn "RENAME '%s' INTO '%s'" name) << transform)
    

    【讨论】:

    • 好了,最后一个表达式看起来不错。显然我缺少一些东西
    • 最后两个(合成的)不正确,因为name 在上下文中不存在(缺少fun name -&gt; 部分。这导致合成不能在那里使用(原样)作为参数需要不止一次
    【解决方案3】:

    这就是我完成这项任务的方式:

    let array = [|
        "one"
        "two"
        "three"
    |]
    
    
    let transform s = s, s + "_transformed"
    
    let printIt (n,t) =  printfn "RENAME '%s' INTO '%s'" n t 
    
    
    array
    |> Array.map transform
    |> Array.iter printIt
    

    我的“最佳实践”告诉我,我始终应该创建和使用函数。这样流程(map 和 iter)是恒定的,函数或数据可能会发生变化。

    “阐明”为什么要使用函数以及不使用函数的附录

    let myPipeLineWithPrint t p a=
        a
        |> Array.map t
        |> Array.iter p
    
    //"Old" Version With above data
    myPipeLineWithPrint transform printIt array
    
    
    type SomeRecord = {
        Name: string
        MoreStuff: string
    }
    
    type OtherRecord = {
        NewName: string
        OldName: string
    }
    
    
    let array2 = [|
        {Name="one"; MoreStuff="dontcare"}
        {Name="two"; MoreStuff="dontcare"}
        {Name="three"; MoreStuff="dontcare"}
    |] 
    
    let transform2 {Name=n; MoreStuff=ms} = transform n
    
    myPipeLineWithPrint transform2 printIt array2
    
    
    let transform3 {Name=n; MoreStuff=_} =
        let (_,nn) = transform n
        {NewName= nn; OldName=n}
    
    let printIt2 {NewName=nn; OldName = o} = printfn "RENAME '%s' INTO '%s'" o nn   
    
    myPipeLineWithPrint transform3 printIt2 array2
    

    【讨论】:

    • 我很感激花时间提供这个答案,但是,我很难从我的问题中看到这个答案。您能否详细说明一下,例如s, s + "_transformed" 这是做什么的?
    • 我已经运行了它,它确实提供了所需的输出,但是我确实觉得这有点抽象,我确实提到你可以通过重构一个函数来做到这一点,但我想尝试让printfn 与管道保持一致,如果有意义的话?
    • @CallumLinington 关键是现在这可能很简单。如果您想在以后的某个时间更改内容,并更改数据在管道期间的定义或处理方式或打印方式,那么您甚至可能有多个打印位置,这是一件好事实际上有功能。管道很可能没问题,但是通过它的数据以及打印数据的方式实际上正在发生变化。
    • 是的,我有点预先保护了我的问题(一个可能很糟糕的解释)我有点想避开这种重用,主要是因为我只专注于语言运算符和语法优先。
    • @CallumLinington 我已经更新了我的答案,试图让我更清楚如何/什么/为什么/在哪里......希望它至少有帮助;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-12
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-24
    相关资源
    最近更新 更多