Printfn 值不是函数,不能在 F# 的交互式窗口中应用



这可能很简单,但我有一个带有简单示例函数的.fs文件。

let printHello = printfn "%A" "Hello"

我已经使用

设置了.fs文件的搜索路径
>#I "PathToMyFSFile"

我已经使用

加载了文件
>#load "Test.fs"

效果很好。现在我想调用这个函数,这个函数实际打印hello到屏幕,但是这太难了

> Test.printHello;;
val it : unit = ()

尝试Test.printHello ();;很好,但是不起作用。我如何让它在屏幕上打印"Hello"?

您当前的printHello实际上不是一个函数。要使它成为一个函数,你需要执行

let printHello() = printfn "%A" "Hello"

注意()

编辑:

当编译器看到你的定义

let printHello = printfn "%A" "Hello"

作为一个简单的数据项传递。例如,考虑这个程序:

let printHello = printfn "%A" "Hello"
printfn "World"
printHello

这将打印"Hello"然后是"World"printHello只有单位类型,所以什么也不做。与

比较
let printHello() = printfn "%A" "Hello"
printfn "World"
printHello()

这里printHello是一个函数。在这种情况下,函数只在显式调用时执行,所以这先输出"World",然后输出"Hello"

正如John已经说过的,您的printHello不是一个函数-它是unit类型的值。当您为printfn提供所有必需的参数时(正如您所做的那样),它执行命令式操作并返回unit(这是一种仅将单个值写入()的类型)。你可以看到,写这个声明会立即打印出来:

> let printHello = printfn "%A" "Hello";;
"Hello"
val printHello : unit = ()

当您以后使用printHello时,它只是引用这个unit值(它不携带任何信息)。

如果您想让它成为一个函数(类型为unit -> unit),每次执行时都会做一些事情,那么您可以使用John发布的示例。

函数printfn没有部分应用,因为您给了它所需的所有参数(因此它可以立即打印)。如果您想使用局部应用程序,您可以使用如下内容:

> let printHello = printfn "%s %s" "Hello";; // Note - didn't give value for second %s
val printHello : string -> unit

现在printHello是一个等待第二个参数然后运行的函数:

> printHello "World";;
Hello World
val it : unit = ()
> printHello "F#";;
Hello F#
val it : unit = ()

在其他答案中已经说过,"printHello"设置为()是单位,printfn的返回值是(),控制台打印是副作用。

使用懒惰:

let printHello = Lazy (fun () ->printfn "%A" "Hello")

> Test.printHello.Value;;
"Hello"
val it : unit = ()
> Test.printHello.Value;;
val it : unit = () //only once

使用Seq:

let printHello = seq { printfn "%A" "Hello"; yield ()}

> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null]
> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null] //many times

相关内容

  • 没有找到相关文章