在 F# 中是否使用空括号表示没有参数?
In F# Are Empty Parenthesis used to indicate no parameter?
给定此 F# 库代码
来自主要
open FileMaint
let log_file = FileMaint.fm.generate_log_file
来自图书馆
module FileMaint
.
.
.
[<AutoOpen>]
(* return_unique_file_name just returns as close to a unique file name piece based on clock time. *)
module fm =
(* Checks for presense of a file name. *)
let is_file_present file_name =
let rc =
if File.Exists file_name then
true
else
false
rc
(* Initialize a log file. *)
let generate_log_file =
let log_file_name =
if File.Exists(base_log_file) then
test_and_reset_unique_file_name local_dir base_log_file
else
base_log_file
use fH = new StreamWriter(log_file_name, true)
fH.WriteLine(generate_time_stamp + ": " + log_file_name + " initialized.")
从我的 "main",我可以进入调用 is_file_present
,但我不能进入,也不会 generate_log_file
执行。
然而,在generate_log_file
库函数上定义括号后,像这样generate_log_file ()
,然后调用它,函数执行(我可以进入函数)
因此,当函数没有参数时,空括号似乎表示占位符。对吗?
空括号是类型 unit
的 值 。此值与任何其他值一样,与数字或字符串没有主要区别。
let a = 5
let b = "abc"
let c = ()
> val a: int = 5
> val b: string = "abc"
> val c: unit = ()
这种类型unit
的特殊之处在于它只有一个值,没有其他值。但在其他方面,它就像任何其他类型一样。您可以将它用于函数参数,例如:
let f (u: unit) = ...
但是因为它只有一个值,所以可以将值本身用作参数模式:
let f () = ...
您也可以对其他类型执行此操作:
let g 42 = ...
let h "abc" = ...
这将编译,但它会警告您 int
除了 42 之外还有其他值,并且您还没有定义该函数应该为它们做什么。但是对于 unit
除了 ()
之外不能有其他值,所以没有警告。您甚至可以自己制作等效类型:
type T = A
let f A = 42 // no warning here, because A is the only possible value of type T
现在,回到您的示例:在您的原始代码中,generate_log_file
不是函数,而是一个值。它是在初始化期间计算的,当您认为自己是 "calling" 它时,您只是在引用该预先计算的值。没有通话正在进行,因为没有什么可通话的。
它是一个值而不是一个函数的原因是它没有任何参数。是的,这是一个简单的规则:如果你有参数,你就是一个函数;如果没有,你就是一个价值。所以一旦你给它一个参数,它就变成了一个函数,这就是你可以介入的原因。
就目前而言,generate_log_file
的值是在初始化模块 fm
时初始化的值,很可能是在程序集启动期间。如果您有策略地插入 Debugger.Break
,这是可调试的。
通过将代码更改为 let generate_log_file () ...
generate_log_file
现在是您使用单位值 ()
调用的函数,从而更易于调试。
在 F# 中,您总是使用单个值调用函数,()
是类型 unit
的唯一值。
PS.
let generate_log_file () ...
使用参数的模式匹配来避免输入 let generate_log_file (_ : unit) ...
。以下也是合法的,尽管有点无用 let generate_log_file 0 ...
.
给定此 F# 库代码
来自主要
open FileMaint
let log_file = FileMaint.fm.generate_log_file
来自图书馆
module FileMaint
.
.
.
[<AutoOpen>]
(* return_unique_file_name just returns as close to a unique file name piece based on clock time. *)
module fm =
(* Checks for presense of a file name. *)
let is_file_present file_name =
let rc =
if File.Exists file_name then
true
else
false
rc
(* Initialize a log file. *)
let generate_log_file =
let log_file_name =
if File.Exists(base_log_file) then
test_and_reset_unique_file_name local_dir base_log_file
else
base_log_file
use fH = new StreamWriter(log_file_name, true)
fH.WriteLine(generate_time_stamp + ": " + log_file_name + " initialized.")
从我的 "main",我可以进入调用 is_file_present
,但我不能进入,也不会 generate_log_file
执行。
然而,在generate_log_file
库函数上定义括号后,像这样generate_log_file ()
,然后调用它,函数执行(我可以进入函数)
因此,当函数没有参数时,空括号似乎表示占位符。对吗?
空括号是类型 unit
的 值 。此值与任何其他值一样,与数字或字符串没有主要区别。
let a = 5
let b = "abc"
let c = ()
> val a: int = 5
> val b: string = "abc"
> val c: unit = ()
这种类型unit
的特殊之处在于它只有一个值,没有其他值。但在其他方面,它就像任何其他类型一样。您可以将它用于函数参数,例如:
let f (u: unit) = ...
但是因为它只有一个值,所以可以将值本身用作参数模式:
let f () = ...
您也可以对其他类型执行此操作:
let g 42 = ...
let h "abc" = ...
这将编译,但它会警告您 int
除了 42 之外还有其他值,并且您还没有定义该函数应该为它们做什么。但是对于 unit
除了 ()
之外不能有其他值,所以没有警告。您甚至可以自己制作等效类型:
type T = A
let f A = 42 // no warning here, because A is the only possible value of type T
现在,回到您的示例:在您的原始代码中,generate_log_file
不是函数,而是一个值。它是在初始化期间计算的,当您认为自己是 "calling" 它时,您只是在引用该预先计算的值。没有通话正在进行,因为没有什么可通话的。
它是一个值而不是一个函数的原因是它没有任何参数。是的,这是一个简单的规则:如果你有参数,你就是一个函数;如果没有,你就是一个价值。所以一旦你给它一个参数,它就变成了一个函数,这就是你可以介入的原因。
就目前而言,generate_log_file
的值是在初始化模块 fm
时初始化的值,很可能是在程序集启动期间。如果您有策略地插入 Debugger.Break
,这是可调试的。
通过将代码更改为 let generate_log_file () ...
generate_log_file
现在是您使用单位值 ()
调用的函数,从而更易于调试。
在 F# 中,您总是使用单个值调用函数,()
是类型 unit
的唯一值。
PS.
let generate_log_file () ...
使用参数的模式匹配来避免输入 let generate_log_file (_ : unit) ...
。以下也是合法的,尽管有点无用 let generate_log_file 0 ...
.