理解 byref、ref 和 &

发布于 2024-10-18 00:37:50 字数 2076 浏览 1 评论 0原文

嗯,我开始了解到 F# 能够管理引用(某种类似于 C++ 的引用)。这使得可以更改在函数中传递的参数值,并且还使程序员能够返回多个值。 然而,这是我需要知道的:

  1. Ref 关键字:关键字 ref 用于从值创建对推断类型的值的引用。所以

    让 myref = ref 10
    

    这意味着 F# 将创建一个 Ref 类型的对象,并将我的 int 10 放在那里(在可变字段中)。

    好的。因此,我假设 ref 用于创建 Ref<'a> 类型的实例。正确吗?

  2. 访问值:为了访问存储在引用中的值,我可以这样做:

    让 myref = ref 10
    让 myval = myref.Value
    让 myval2 = !myref
    

    虽然 := 运算符只是让我编辑值,如下所示:

    让 myref = ref 10
    myref.Value <- 30
    我的参考:= 40
    

    所以 ! (Bang) 取消引用我的引用。然后 := 编辑它。我想这也是正确的。

  3. &操作员:这个操作员做什么?它是否应用于引用类型?不,我想它必须应用于可变值,这会返回什么?参考?地址?如果使用交互式:

    让可变的mutvar = 10;;
    &a;;
    

    最后一行抛出错误,因此我不明白 & 运算

  4. ByRef:byref 怎么样?这对我来说非常重要,但我意识到我不明白。 据我所知,它用于有关参数传递的函数。当一个人希望可以编辑传递的值时,可以使用 byref (这有点违背函数式语言的哲学,但 f# 的作用远不止于此)。考虑以下因素:

    let myfunc (x: int byref) =
        x < - x + 10
    

    这很奇怪。我知道,如果您有一个引用 let myref = ref 10 ,然后执行以下操作来编辑值:myref <- 10 则会出现错误,因为它应该像这个:myref := 10。然而,在该函数中,我可以使用 <- 运算符编辑 x,这意味着 x 不是引用,对吗?< /p>

    如果我假设 x 不是引用,那么我还假设在函数中,当在参数上使用 byref 时,该参数可以具有可变语法应用于.所以这只是一个语法问题,如果我假设这我没问题,而且事实上,一切正常(没有编译器错误)。但是,x 是什么?

  5. 调用函数:如何使用利用 byref 参数的函数?

    涉及到 & 运算符,但是您能更好地解释一下吗?在本文中:MSDN 参数和参数提供了以下示例:< /p>

    类型增量器(z) =
        成员 this.Increment(i : int byref) =
           i <- i + z
    
    让增量器 = 新增量器(1)
    让可变的 x = 10
    // A:不推荐:实际上不增加变量。 (我:为什么?)
    增量器.Increment(ref x)
    // 打印 10。
    printfn "%d" x  
    
    让可变 y = 10
    incrementor.Increment(&y) (*我:&它返回什么?*)
    // 打印 11。
    printfn "%d" y 
    
    让 refInt = ref 10
    incrementor.Increment(refInt) (* 为什么它在 A 中不起作用,但在这里却起作用? *)
    // 打印 11。
    printfn "%d" !refInt
    

Well, I came to understand that F# is able to manage references (some sort of C++ like references). This enables the possibilities to change value of parameters passed in functions and also enables the programmer to return more than a single value.
However here's what I need to know:

  1. Ref keyword: The keyword ref is used to create, from a value, a reference to that value of the inferred type. So

    let myref = ref 10
    

    This means that F# will create an object of type Ref<int> putting there (in the mutable field) my int 10.

    OK. So I assume that ref is used to create instances of the Ref<'a> type. Is it correct?

  2. Access value: In order to access a value stored in reference I can do this:

    let myref = ref 10
    let myval = myref.Value
    let myval2 = !myref
    

    While the := operator just lets me edit the value like this:

    let myref = ref 10
    myref.Value <- 30
    myref := 40
    

    So ! (Bang) dereferences my reference. And := edit it. I suppose this is correct too.

  3. The & operator: What does this operator do? Is it to be applied to a reference type? No, I guess it must be applied to a mutable value and this returns what? The reference? The address? If using interactive:

    let mutable mutvar = 10;;
    &a;;
    

    The last line throws an error so I do not understand what the & operator is for.

  4. ByRef: What about byref? That's very important to me, but I realize I do not understand it.
    I understand it is used in function regarding parameter passing. One uses byref when he wants that the passed value can be edited (this is a bit against the functional languages' philosophy but f# is something more than that). Consider the following:

    let myfunc (x: int byref) =
        x <- x + 10
    

    This is strange. I know that if you have a reference let myref = ref 10 and then do this to edit the value: myref <- 10 it arises an error because it should be like this: myref := 10. However, the fact that in that function I can edit x using the <- operator means that x is not a reference, right?

    If I assume that x is not a reference, then I assume also that, in functions, when using byref on a parameter, that parameter can have the mutable syntax applied to. So it is just a matter of syntax, if I assume this I am OK, and, in fact, everything works (no compiler errors). However, what is x?

  5. Calling functions: How can I use a function utilizing byref parameters?

    The & operator is involved but could you explain this better please? In this article: MSDN Parameters and Arguments the following example is provided:

    type Incrementor(z) =
        member this.Increment(i : int byref) =
           i <- i + z
    
    let incrementor = new Incrementor(1)
    let mutable x = 10
    // A: Not recommended: Does not actually increment the variable. (Me: why?)
    incrementor.Increment(ref x)
    // Prints 10.
    printfn "%d" x  
    
    let mutable y = 10
    incrementor.Increment(&y) (* Me: & what does it return? *)
    // Prints 11.
    printfn "%d" y 
    
    let refInt = ref 10
    incrementor.Increment(refInt) (* Why does it not work in A, but here it does? *)
    // Prints 11.
    printfn "%d" !refInt
    

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

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

发布评论

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

评论(1

别挽留 2024-10-25 00:37:50

Ref 关键字 是的,当您编写 let a = ref 10 时,您实际上是在编写 let a = new Ref(10) 其中Ref 类型具有可变字段 Value

访问值 :=! 运算符只是书写的快捷方式:

a.Value <- 10  // same as writing: a := 10
a.Value        // same as writing: !a

ByRef 是一种特殊类型,可以(合理地)仅在方法参数中使用。这意味着参数本质上应该是指向某个内存位置(分配在堆或堆栈上)的指针。它对应于 C# 中的 outref 修饰符。请注意,您无法创建这种类型的局部变量。

&运算符是一种创建值(指针)的方法,该值可以作为参数传递给需要 byref 类型的函数/方法。

调用函数 使用 byref 的示例之所以有效,是因为您向该方法传递了对本地可变变量的引用。通过引用,该方法可以更改存储在该变量中的值。

以下内容不起作用:

let a = 10            // Note: You don't even need 'mutable' here
bar.Increment(ref a)  

原因是您正在创建 Ref 的新实例,并将 a 的值复制到该实例中。然后,Increment 方法会修改 Ref 实例中存储在堆上的值,但您不再拥有对此对象的引用。

let a = ref 10
bar.Increment(a)  

这是可行的,因为 aRef 类型的值,并且您将指向堆分配实例的指针传递给 Increment然后使用 !a 从堆分配的引用单元中获取值。

(您可以使用使用 ref 创建的值作为 byref 的参数,因为编译器会专门处理这种情况 - 它将自动引用 Value 字段因为这是一个有用的场景...)。

Ref keyword Yes, when you write let a = ref 10 you're essentially writing let a = new Ref<int>(10) where the Ref<T> type has a mutable field Value.

Access value The := and ! operators are just shortcuts for writing:

a.Value <- 10  // same as writing: a := 10
a.Value        // same as writing: !a

ByRef is a special type that can be (reasonably) used only in method parameters. It means that the argument should be essentially a pointer to some memory location (allocated on heap or stack). It corresponds to out and ref modifiers in C#. Note that you cannot create local variable of this type.

The & operator is a way to create a value (a pointer) that can be passed as an argument to a function/method expecting a byref type.

Calling functions the example with byref works because you're passing the method a reference to a local mutable variable. Via the reference, the method can change the value stored in that variable.

The following doesn't work:

let a = 10            // Note: You don't even need 'mutable' here
bar.Increment(ref a)  

The reason is that you're creating a new instance of Ref<int> and you're copying the value of a into this instance. The Increment method then modifies the value stored on heap in the instance of Ref<int>, but you don't have a reference to this object anymore.

let a = ref 10
bar.Increment(a)  

This works, because a is a value of type Ref<int> and you're passing a pointer to the heap-allocated instance to Increment and then get the value from heap-allocated reference cell using !a.

(You can use values created using ref as arguments for byref because the compiler handles this case specially - it will automatically take reference of the Value field because this is a useful scenario...).

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