F#按参考传递

时间:2015-05-11 16:28:06

标签: f# functional-programming pass-by-reference out ref

我试图在F#中通过引用传递。在C#中,使用ref和out关键字非常简单,但在F#中看起来并不那么简单。我刚读过这个:http://davefancher.com/2014/03/24/passing-arguments-by-reference-in-f/,建议使用参考单元格。 (我想这意味着在C#中没有类似于out关键字的地方,你不必初始化一个变量来传递它。)

但无论如何,我想知道这是否是在F#中通过引用传递的最佳/唯一方式,如果这在功能语言中甚至是一个好主意。

编辑:

我很感兴趣因为我刚才意识到异常会减慢我的代码速度。我正在进行十字军东征以消除它们。基本上,我的计划是这样的:假设一个函数返回一个double或者如果有错误则抛出异常。相反,我将通过引用传递double和ErrorCode类型作为位掩码,然后传递值和错误。我猜测我必须让所有这些变量变得可变。

4 个答案:

答案 0 :(得分:4)

您的问题有很多部分我会尽力回答:

  •   

    建议使用参考单元

    • 是的,参考单元格(或参考单元格)是将可变数据传递到函数中的惯用方法
  •   

    我想这意味着C#中的out关键字没有模拟,你不必初始化一个变量来传递它。

    • C#通常使用out参数来表示其他返回值。在F#中执行此操作的惯用方法是使用元组。例如,C#函数int TryParse(string s, out bool succeeded)只是TryParse(s : string) -> (int, bool)
  •   

    如果在功能语言中这甚至是一个好主意。

    • 这肯定不是我认为是正常的,惯用的F#代码。我代表可能的结果的方式是代表可能的结果:
type MyFunctionResult = 
    | Success of double
    | ErrorCase1
    | ErrorCase2 of AddditionalDataType

如果你有许多使用这种风格的功能,那就是very easy to compose them together with a bind function

答案 1 :(得分:2)

您可以使用| DEBUG: Executing shell function do_patch | Deleted branch meta-temp (was d36a7ef). | [INFO] validating against known patches (qemuarm-standard-meta) ERROR. could not update git tree################## ] (\)(94 %)) | ERROR: Could not apply patches for qemuarm. | ERROR: Patch failures can be resolved in the devshell (bitbake -c devshell linux-yocto) 代替C#的&,但前缀为ref的变量必须是可变的。一篇很好的文章甚至涵盖了PInvoke陷阱:https://pblasucci.wordpress.com/2012/07/23/managing-pointers-or-fs-platform-invoke-gotcha/

&

答案 2 :(得分:0)

让我描述一下OCaml的作用,因为我不知道F#,有人可以确认F#足够相似,我的答案适用。

在OCaml或F#等函数式编程语言中,默认情况下 immutable 。也就是说,你需要在它们之前声明事物是可变的,事实上,可变数据结构不像不可变数据结构那么常见(但并不罕见)。

现在,因为默认情况下数据是不可变的,所以传递参数无关紧要,因为它们无论如何都不会被改变。在这种情况下,通过值传递适合寄存器的简单数据类型以及通过引用传递其他所有内容是有意义的。

当然,可变数据类型是通过引用传递的,否则就没有什么价值。

也许你可以给我们一个你想要做的事情的例子。您是否传递可变或不可变数据?

答案 3 :(得分:0)

我刚刚在F#中收到一条错误消息,告诉我我需要obj ref并且仅传递obj

browser.Navigate2(url_obj)

所以我刚刚添加ref并且它有效

browser.Navigate2(ref url_obj)

所以我想你只需添加ref

使用COM对象时非常有用。