F# 通过引用传递
F# pass by reference
我试图在 F# 中通过引用传递。在 C# 中,使用 ref 和 out 关键字非常容易,但在 F# 中似乎并没有那么简单。我刚刚读到:http://davefancher.com/2014/03/24/passing-arguments-by-reference-in-f/,它建议使用参考单元格。 (我想这意味着 C# 中没有类似 out 关键字的东西,你不必初始化变量就可以传递它。)
但无论如何,我想知道这是否是 best/only 在 F# 中通过引用传递的方式,以及这在函数式语言中是否是个好主意。
编辑:
我很感兴趣,因为我刚刚意识到异常正在减慢我的代码。我正在进行消灭他们的运动。基本上,我的计划是这样的:说一个函数 returns a double 或如果有错误则抛出异常。相反,我将通过引用传递一个双精度类型和一个 ErrorCode 类型作为位掩码,然后向下传递值和错误。我猜我只需要让所有这些变量可变。
让我描述一下 OCaml 的作用,因为我不了解 F#,但有人可以确认 F# 足够相似,我的回答适用。
在 OCaml 或 F# 等函数式编程语言中,默认情况下数据是 不可变的。也就是说,你需要先声明它们是可变的,事实上可变数据结构不如不可变数据结构常见(但并不少见)。
现在,因为默认情况下数据是不可变的,所以您如何传递参数并不重要,因为它们无论如何都不会被更改。在这些情况下,传递简单的数据类型是有意义的,这些数据类型按值适合寄存器,其他所有内容均按引用。
当然,可变数据类型是通过引用传递的,否则拥有它们就没有什么价值了。
或许您可以举例说明您正在尝试做什么。您传递的是可变数据还是不可变数据?
您可以使用 &
代替 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#
您的问题包含多个部分,我将尽力回答:
which suggests using a reference cell
- 是的,参考单元格(或参考单元格)是将可变数据传递给函数的惯用方式
I suppose this means there is no analog to the out keyword in C# where you don't have to initialize a variable to pass it.
- C# 通常使用
out
参数来表示额外的 return 值。在 F# 中执行此操作的惯用方法是使用元组。例如 C# 函数 int TryParse(string s, out bool succeeded)
就是 TryParse(s : string) -> (int, bool)
if this is even a good idea in a functional language.
- 这肯定不是我认为的正常、惯用的 F# 代码。我表示的方式是用一个代表可能结果的歧视联盟:
type MyFunctionResult =
| Success of double
| ErrorCase1
| ErrorCase2 of AddditionalDataType
等等
如果您有多个函数使用这种样式,那就是 very easy to compose them together with a bind
function。
我刚刚在 F# 中收到一条错误消息,告诉我我需要 obj ref
并且只传递了 obj
browser.Navigate2(url_obj)
所以我刚刚添加了 ref
并且成功了
browser.Navigate2(ref url_obj)
所以我猜你只需添加 ref
。
它在处理 COM 对象时非常有用。
我试图在 F# 中通过引用传递。在 C# 中,使用 ref 和 out 关键字非常容易,但在 F# 中似乎并没有那么简单。我刚刚读到:http://davefancher.com/2014/03/24/passing-arguments-by-reference-in-f/,它建议使用参考单元格。 (我想这意味着 C# 中没有类似 out 关键字的东西,你不必初始化变量就可以传递它。)
但无论如何,我想知道这是否是 best/only 在 F# 中通过引用传递的方式,以及这在函数式语言中是否是个好主意。
编辑:
我很感兴趣,因为我刚刚意识到异常正在减慢我的代码。我正在进行消灭他们的运动。基本上,我的计划是这样的:说一个函数 returns a double 或如果有错误则抛出异常。相反,我将通过引用传递一个双精度类型和一个 ErrorCode 类型作为位掩码,然后向下传递值和错误。我猜我只需要让所有这些变量可变。
让我描述一下 OCaml 的作用,因为我不了解 F#,但有人可以确认 F# 足够相似,我的回答适用。
在 OCaml 或 F# 等函数式编程语言中,默认情况下数据是 不可变的。也就是说,你需要先声明它们是可变的,事实上可变数据结构不如不可变数据结构常见(但并不少见)。
现在,因为默认情况下数据是不可变的,所以您如何传递参数并不重要,因为它们无论如何都不会被更改。在这些情况下,传递简单的数据类型是有意义的,这些数据类型按值适合寄存器,其他所有内容均按引用。
当然,可变数据类型是通过引用传递的,否则拥有它们就没有什么价值了。
或许您可以举例说明您正在尝试做什么。您传递的是可变数据还是不可变数据?
您可以使用 &
代替 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#
您的问题包含多个部分,我将尽力回答:
which suggests using a reference cell
- 是的,参考单元格(或参考单元格)是将可变数据传递给函数的惯用方式
I suppose this means there is no analog to the out keyword in C# where you don't have to initialize a variable to pass it.
- C# 通常使用
out
参数来表示额外的 return 值。在 F# 中执行此操作的惯用方法是使用元组。例如 C# 函数int TryParse(string s, out bool succeeded)
就是TryParse(s : string) -> (int, bool)
- C# 通常使用
if this is even a good idea in a functional language.
- 这肯定不是我认为的正常、惯用的 F# 代码。我表示的方式是用一个代表可能结果的歧视联盟:
type MyFunctionResult =
| Success of double
| ErrorCase1
| ErrorCase2 of AddditionalDataType
等等
如果您有多个函数使用这种样式,那就是 very easy to compose them together with a bind
function。
我刚刚在 F# 中收到一条错误消息,告诉我我需要 obj ref
并且只传递了 obj
browser.Navigate2(url_obj)
所以我刚刚添加了 ref
并且成功了
browser.Navigate2(ref url_obj)
所以我猜你只需添加 ref
。
它在处理 COM 对象时非常有用。