【问题标题】:F# pass by referenceF# 通过引用传递
【发布时间】:2015-07-22 06:23:38
【问题描述】:

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

但无论如何,我想知道这是否是在 F# 中通过引用传递的最佳/唯一方法,以及在函数式语言中这是否是一个好主意。

编辑:

我很感兴趣,因为我刚刚意识到异常会减慢我的代码速度。我正在努力消灭他们。基本上,我的计划是这样的:假设一个函数返回一个双精度值,或者如果有错误则抛出一个异常。相反,我将通过引用传递一个 double 和一个 ErrorCode 类型作为位掩码,然后将值和错误向下传递。我猜我只需要让所有这些变量都是可变的。

【问题讨论】:

  • 为什么需要这样做?如果要能够调用现有的 BCL 方法,如 TryParse,请按以下步骤操作:stackoverflow.com/a/13589596/126014
  • @WesleyWiser 给出的答案是正确的,但我只想添加以下内容。试图将 C# 一对一地翻译成 F# 是错误的。不要这样做,否则您将不可避免地陷入与当前绑定一样的困境。相反,请查看您尝试解决的实际问题,而不是某些语言的特定技术细节。在这种情况下:“实际问题”是“报告错误”,“技术细节”是“按引用参数”。

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


【解决方案1】:

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

browser.Navigate2(url_obj)

所以我刚刚添加了ref,它起作用了

browser.Navigate2(ref url_obj)

所以我猜你只需添加ref

在处理 COM 对象时非常有用。

【讨论】:

    【解决方案2】:

    您的问题有很多部分,我将尝试回答:

    • 建议使用参考单元格

      • 是的,参考单元(或参考单元)是将可变数据传递给函数的惯用方式
    • 我想这意味着在 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

    【讨论】:

      【解决方案3】:

      您可以使用& 代替C# 的ref,但以& 为前缀的变量必须是可变的。一篇很好的文章,甚至涵盖了 PInvoke 陷阱:https://pblasucci.wordpress.com/2012/07/23/managing-pointers-or-fs-platform-invoke-gotcha/

        open System.Collections.Generic
        let dic = new Dictionary<string, string>()
        dic.Add("key", "myvalue")
        let mutable v = "" // v is mutable
        let success = dic.TryGetValue("key", &v);
        System.Console.WriteLine(v)
        let succ, value = dic.TryGetValue("key") // this is what Mark Seemann says is the comment, a shortcut for C#'s `Try...(.., out ...)` is using tuples in F#
      

      【讨论】:

        【解决方案4】:

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

        在 OCaml 或 F# 等函数式编程语言中,默认情况下数据是不可变的。也就是说,您需要先声明事物是可变的,实际上可变数据结构不如不可变数据结构常见(但并不罕见)。

        现在,由于默认情况下数据是不可变的,因此您如何传递参数并不重要,因为它们无论如何都不会改变。在这些情况下,传递简单的数据类型是有意义的,这些数据类型按值放入寄存器,其他所有内容按引用。

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

        也许你可以给我们一个你正在尝试做的例子。您是在传递可变数据还是不可变数据?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-01-12
          • 2013-09-10
          • 2020-04-01
          • 1970-01-01
          • 2011-06-28
          • 2015-05-02
          • 2012-03-13
          • 2015-06-04
          相关资源
          最近更新 更多