简体   繁体   English

"Hello" |> printfn 在 F# 中生成错误

[英]"Hello" |> printfn generates an error in F#

https://tryfsharp.fsbolero.io/ https://tryfsharp.fsbolero.io/

printfn "Hello"

works as expected without errors, however, using pipe operator但是,使用 pipe 运算符按预期工作,没有错误

"Hello" |> printfn

The type 'string' is not compatible with the type 'Printf.TextWriterFormat' “字符串”类型与“Printf.TextWriterFormat”类型不兼容

I understood the pipe operator behavior:我了解 pipe 操作员行为:

f(a) is equivalent to a |> f f(a)等价于a |> f

Why does the latter generate the error??为什么后者会产生错误? Thanks.谢谢。

Yes.是的。 The pipe operator does what you think it does. pipe 运算符按照您的想法执行。 However, printfn is "special" that it takes a kind of "formattable string" (there are different kinds of these) and the compiler does its magic only when the format string appears as a direct argument.但是, printfn是“特殊的”,它采用一种“可格式化的字符串”(有不同的类型),并且编译器只有在格式字符串作为直接参数出现时才会发挥作用。

In other words, your "Hello" in the first example is not really a string, it is a Printf.TextWriterFormat object, magically created by the compiler.换句话说,第一个示例中的"Hello"并不是真正的字符串,它是由编译器神奇地创建的Printf.TextWriterFormat object。

Still, you can do what you want by using an explict format string.不过,您可以通过使用显式格式字符串来做您想做的事情。 This approach you'll see quite a bit in real-world code:这种方法你会在现实世界的代码中看到很多:

"Hello" |> printfn "%s"

Here, %s means: give me a string.在这里, %s意思是:给我一个字符串。 The magic of F# in this case again takes the format string, here "%s" , this time with an argument of type string , and turns it into a function.在这种情况下,F# 的魔力再次采用格式字符串,这里"%s" ,这次使用string类型的参数,并将其转换为 function。

Note 1: that this "surprise effect" is being considered and the community works towards adding a printn function (ie, without the f which stands for format ) to just take a simple string: https://github.com/fsharp/fslang-suggestions/issues/1092注意1:正在考虑这种“惊喜效应”,社区致力于添加一个printn function (即,没有代表formatf )只取一个简单的字符串: https://github.com/fsharp/fslang -建议/问题/1092

Note 2: if you do want to pass arguments to printfn around, you can make the type explicit, but this is done very rarely:注意 2:如果您确实想将 arguments 传递给printfn ,则可以使类型显式,但很少这样做:

let x = Printf.TextWriterFormat<unit> "Hello"
x |> printfn  // now it's legal

Note 3: you might wonder why the compiler doesn't apply its magic to the lh-side of |> as well.注意 3:您可能想知道为什么编译器也不将其魔法应用于|>的 lh 侧。 The reason is that |> is not an intrinsic to the compiler, but just another overridable operator.原因是|>不是编译器固有的,而只是另一个可覆盖的运算符。 Fixing this is therefor technically very hard (there can be any amount of operators on the lh-side), though it has been considered at certain times.因此,解决这个问题在技术上非常困难(左侧可以有任意数量的运算符),尽管在某些时候已经考虑过。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM