在复杂函数中返回值时出现问题。示例总是更好:
考虑以下功能:
let myf (mypar: int) =
mypar + 1
这里没有问题,这个函数编译正确,签名是:
val myf: int -> int
好的,好吧。现在考虑这段代码:
let myf (mypar: int) =
if mypar = 2 then
4 (* ERROR *)
mypar + 1
这不起作用:
这个表达式应该有类型单位,但这里有int
当我在if
,while
a for
或其他所有区域内尝试从我的函数返回时,会出现此错误。我认为问题是确保所有可能的返回路径返回相同的类型,但在这里我不明白会发生什么。
请注意,如果我插入()
单位,则所有内容都有效:
let myf (mypar: int) =
if mypar = 2 then
() (* No error *)
mypar + 1
但那个单位不能让我的功能恢复!它继续!!! 此外,你能解释一下F#如何处理这个???
三江源
答案 0 :(得分:13)
要添加更多详细信息,您的方法存在的问题是F#中的所有内容都是表达式。这样可以更容易地推理您的程序(因为您不需要跟踪当前正在执行的语句),但这意味着您始终必须编写完整的表达式。
如果您尝试编写类似return
的内容,就好像您在C#中编写了以下内容(这可能解释了为什么F#不允许这样的事情):
int a = 10 + (3 * (return 10; 2));
return a;
为什么写if .. then ()
时没有收到错误? ()
表达式创建一个特殊的类型unit
的值,因为它只有一个有效值。 F#允许您在返回if .. then
时不else
编写unit
,因为它可以确定else
分支必须返回唯一的现有单位值,因此它会看到您的代码为:
if something then ()
else () // implicitly added by the compiler
唯一的区别是抛出异常(使用raise
),其行为就像在C#中一样。您可以使用异常中断函数,但更好的方法是重写代码以获得完整的有效表达式。
答案 1 :(得分:8)
F#没有退货声明。只需if
else
let myf (mypar: int) =
if mypar = 2 then
4
else
mypar + 1
就可以选择一个区块或另一个区块来执行您想要的操作的唯一方法。{/ 1}}
let myf (mypar: int) =
if mypar = 2 then
failwith "invalid argument"
mypar + 1
或者,抛出异常会提前退出函数:
{{1}}
答案 2 :(得分:3)
您是否尝试过使用else
?
let myf (mypar: int) =
if mypar = 2 then
4
else
mypar + 1
我自己没试过,但值得一试:)
(当然也考虑使用模式匹配。)