F#:函数中返回点较多,如何处理?

发布于 10-18 13:33 字数 706 浏览 4 评论 0原文

在复杂函数中返回值时遇到问题。例子总是更好:

考虑下面的函数:

let myf (mypar: int) =
   mypar + 1

这​​里没有探针,这个函数编译正确,签名是:

val myf: int -> int

好的,好吧。现在考虑这段代码:

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

这不起作用:

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

每当我尝试从函数返回时,当我在if,一个< code>while 一个 for 或每个其他块。我认为问题在于确保所有可能的返回路径返回相同的类型,但这里我不明白会发生什么。

请注意,如果我插入一个 () 单元,则一切正常:

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

但是该单元不会使我的函数返回!它继续! 此外,你能解释一下 F# 如何处理这个问题吗???

谢谢

I have a problem when returning values in complex functions. Examples are always better:

Consider the following function:

let myf (mypar: int) =
   mypar + 1

Well no probel here, this function is compiled correctly and the signature is:

val myf: int -> int

OK, well. Now consider this code:

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

This does not work:

This expression was expected to have type unit but here has int

This error is raised everytime I try to return from my function when I am inside a if, a while a for or every other block. I thought that the problem was assuring that all possible return paths return the same type, but here I do not understand what happens.

Please note that if I insert a () unit everything works for example:

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

But that unit does not make my function return!!! it continues!!!
Furthermore, could you please explain me how F# handles this???

Thankyou

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

沒落の蓅哖2024-10-25 13:33:51

要添加更多细节,您的方法的问题在于 F# 中的所有内容都是表达式。这使得推理程序变得更加容易(因为您不需要跟踪当前正在执行的语句),但这意味着您始终必须编写完整的表达式。

如果您尝试编写类似 return 的内容,就好像您在 C# 中编写了以下内容(这可能解释了为什么 F# 不允许此类操作):

int a = 10 + (3 * (return 10; 2));
return a;

为什么您没有收到错误当你写if .. then ()时? () 表达式创建一个特殊的 unit 类型值,因为它只有一个有效值。 F# 允许您在返回 unit 时编写 if .. then 而无需使用 else,因为它可以计算出 else > 分支必须返回唯一现有的单位值,因此它将您的代码视为:

if something then ()
else () // implicitly added by the compiler

唯一的区别是抛出异常(使用 raise),其行为与 C# 中一样。您可以使用异常来中断函数,但最好重写代码以获得完整的有效表达式。

To add some more details, the problem with your approach is that everything in F# is an expression. This makes it a lot easier to reason about your programs (because you don't need to keep track of the currently executing statement), but it means that you always have to write a complete expression.

If you try to write something like return, it would be as if you wrote the following in C# (This probably explains why F# doesn't allow this kind of things):

int a = 10 + (3 * (return 10; 2));
return a;

Why didn't you get error when you wrote if .. then ()? The () expression creates a value of type unit that is special, because it has only one valid value. F# allows you to write if .. then without else when returning unit, because it can figure out that the else branch has to return the only existing unit value, so it sees your code as:

if something then ()
else () // implicitly added by the compiler

The only difference is throwing an exception (using raise) which behaves just like in C#. You could break out of a function using exception, but it is much better idea to rewrite the code to have a complete valid expression.

羁拥2024-10-25 13:33:51

F# 没有 return 语句。在这里执行您想要的操作(选择一个块或另一个块)的唯一方法是使用 if .. else

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

或者,抛出异常会提前退出函数:

let myf (mypar: int) =
   if mypar = 2 then
      failwith "invalid argument"

   mypar + 1

F# has no return statement. The only way to do what you want to here, to choose either one block or the other, is with if .. else:

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

Alternatively, throwing an exception exits the function early:

let myf (mypar: int) =
   if mypar = 2 then
      failwith "invalid argument"

   mypar + 1
夏日落2024-10-25 13:33:51

您是否尝试过使用 else 来代替?

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

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

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

Have you tried using an else instead?

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

I haven't tried it myself, but it's worth a shot :)

(Also consider using pattern matching instead, of course.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文