質問

まあ、私はF#が参照(参照のようなある種のC++)を管理できることを理解するようになりました。これにより、関数で渡されたパラメータの値を変更する可能性が可能になり、プログラマは複数の値を返すこともできます。しかし、ここに私が知る必要があるものがあります:

  1. Refキーワード:キーワード ref 値から、推論された型のその値への参照を作成するために使用されます。だから

    let myref = ref 10
    

    これは、F#が型のオブジェクトを作成することを意味します Ref<int> そこに置く(可変フィールドに)私の int 10.

    わかっただから私はそれを前提としています ref のインスタンスを作成するために使用されます Ref<'a> タイプ。それは正しいですか?

  2. アクセス値:参照に格納されている値にアクセスするために、私はこれを行うことができます:

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

    一方、 := 演算子はちょうど私がこのような値を編集することができます:

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

    だから ! (バン)私の参照を逆参照します。と := それを編集します。これも正しいと思います。

  3. 演算子(&):この演算子は何をしますか?参照型に適用されますか?いいえ、私はそれが変更可能な値に適用されなければならないと思います、そしてこれは何を返しますか?参考にしてみませんか?住所は?対話型を使用している場合:

    let mutable 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 参照ではありませんよね?

    私がそれを仮定した場合 x は参照ではありませんが、関数では、次を使用するときにも想定しています byref パラメーターでは、そのパラメーターに変更可能な構文を適用できます。だから、私がこれを私が大丈夫だと仮定すれば、それは構文の問題です、そして、実際には、すべてがうまくいきます(コンパイラエラーはありません)。しかし、何ですか x?

  5. 関数の呼び出し:Byrefパラメータを利用した関数を使用するにはどうすればよいですか?

    ザ- & オペレーターが関与していますが、これをよりよく説明できますか?この記事の内容: MSDNのパラメータと引数 次の例を示します:

    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
    
役に立ちましたか?

解決

Refキーワード はい、あなたが書くとき let a = ref 10 あなたは本質的に書いています let a = new Ref<int>(10) ここで、 Ref<T> 型には可変フィールドがあります Value.

アクセス値 ザ- :=! 演算子は書くための単なるショートカットです:

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

ByRef メソッドパラメータでのみ(合理的に)使用できる特別な型です。これは、引数が本質的に(ヒープまたはスタックに割り当てられた)いくつかのメモリ位置へのポインタであるべきであることを意味します。それはに対応します outref c#の修飾子。この型のローカル変数は作成できないことに注意してください。

演算子(&) を期待する関数/メソッドに引数として渡すことができる値(ポインタ)を作成する方法です byref タイプ。

関数の呼び出し との例 byref ローカルの可変変数への参照をメソッドに渡しているために機能します。参照を介して、メソッドはその変数に格納されている値を変更できます。

以下は動作しません:

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

その理由は、次の新しいインスタンスを作成しているためです Ref<int> そして、あなたはの値をコピーしています a このインスタンスに。ザ- Increment メソッドは、次のインスタンスのヒープに格納されている値を変更します Ref<int>, 、しかし、あなたはもうこのオブジェクトへの参照を持っていません。

let a = ref 10
bar.Increment(a)  

これは動作します。 a 型の値です Ref<int> そして、ヒープに割り当てられたインスタンスへのポインタを渡しています Increment そして、ヒープ割り当てされた参照セルから値を取得します !a.

(以下を使用して作成された値を使用できます ref の引数として byref コンパイラはこのケースを特別に処理するので、自動的に参照を取ります Value これは便利なシナリオであるため、フィールド。..).

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top