F#:函数中有更多返回点,如何处理它们?

时间:2011-02-21 16:25:50

标签: .net f# functional-programming return unit-type

在复杂函数中返回值时出现问题。示例总是更好:

考虑以下功能:

let myf (mypar: int) =
   mypar + 1

这里没有问题,这个函数编译正确,签名是:

val myf: int -> int
好的,好吧。现在考虑这段代码:

let myf (mypar: int) =
   if mypar = 2 then
      4 (* ERROR *)
   mypar + 1

这不起作用:

这个表达式应该有类型单位,但这里有int

当我在ifwhile a for或其他所有区域内尝试从我的函数返回时,会出现此错误。我认为问题是确保所有可能的返回路径返回相同的类型,但在这里我不明白会发生什么。

请注意,如果我插入()单位,则所有内容都有效:

let myf (mypar: int) =
   if mypar = 2 then
      () (* No error *)
   mypar + 1

但那个单位不能让我的功能恢复!它继续!!! 此外,你能解释一下F#如何处理这个???

三江源

3 个答案:

答案 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

我自己没试过,但值得一试:)

(当然也考虑使用模式匹配。)