2

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

let printHello = printfn "%A" "Hello"

我已经使用 .fs 文件设置了搜索路径

>#I "PathToMyFSFile"

我已经使用加载了我的文件

>#load "Test.fs"

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

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

试过 Test.printHello();; 也一样,但不起作用。我实际上如何让它在屏幕上打印“Hello”?

4

3 回答 3

6

你的电流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"then "Hello"

于 2011-11-11T09:16:00.827 回答
5

正如约翰已经说过的,你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 = ()
于 2011-11-11T10:13:55.577 回答
1

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

使用懒惰:

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

演示

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

使用序列:

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
于 2011-11-11T11:52:34.717 回答