这可能很简单,但我有一个带有简单示例函数的.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