And*_*dry 6 .net f# functional-programming return unit-type
在复杂函数中返回值时出现问题.示例总是更好:
考虑以下功能:
let myf (mypar: int) =
mypar + 1
Run Code Online (Sandbox Code Playgroud)
这里没有问题,这个函数编译正确,签名是:
val myf: int -> int
Run Code Online (Sandbox Code Playgroud)
好吧好吧.现在考虑这段代码:
let myf (mypar: int) =
if mypar = 2 then
4 (* ERROR *)
mypar + 1
Run Code Online (Sandbox Code Playgroud)
这不起作用:
这个表达式应该有类型单位,但这里有int
每当我尝试从我的函数返回时,当我在a if
,while
a for
或其他每个块中时,都会引发此错误.我认为问题是确保所有可能的返回路径返回相同的类型,但在这里我不明白会发生什么.
请注意,如果我插入一个()
单元,一切都可以工作,例如:
let myf (mypar: int) =
if mypar = 2 then
() (* No error *)
mypar + 1
Run Code Online (Sandbox Code Playgroud)
但那个单位不会让我的功能恢复!它继续!!! 此外,你能解释一下F#如何处理这个???
谢谢
Tom*_*cek 14
要添加更多细节,您的方法的问题是F#中的所有内容都是表达式.这样可以更容易地推理您的程序(因为您不需要跟踪当前正在执行的语句),但这意味着您始终必须编写完整的表达式.
如果您尝试编写类似的内容return
,就好像您在C#中编写了以下内容(这可能解释了为什么F#不允许这样的事情):
int a = 10 + (3 * (return 10; 2));
return a;
Run Code Online (Sandbox Code Playgroud)
你写的时为什么不出错if .. then ()
?该()
表达式创建类型的值unit
是特殊的,因为它只有一个有效的价值.F#允许您在返回时if .. then
不写,因为它可以判断分支必须返回唯一的现有单位值,因此它将您的代码视为:else
unit
else
if something then ()
else () // implicitly added by the compiler
Run Code Online (Sandbox Code Playgroud)
唯一的区别是抛出异常(使用raise
),其行为就像在C#中一样.您可以使用异常中断函数,但更好的想法是重写代码以获得完整的有效表达式.
F#没有返回语句.在这里做你想做的事情,选择一个块或另一个块的唯一方法是if
... else
:
let myf (mypar: int) =
if mypar = 2 then
4
else
mypar + 1
Run Code Online (Sandbox Code Playgroud)
或者,抛出异常会提前退出函数:
let myf (mypar: int) =
if mypar = 2 then
failwith "invalid argument"
mypar + 1
Run Code Online (Sandbox Code Playgroud)