リストを別のリストに追加するということは、最初のリストからオブジェクトをコピーし、次に説明されているように、追加されたリストを指すことを意味すると常に考えていました。ただし、このブログ投稿とそのコメントでは、コピーされるのはポインターのみであり、基になるオブジェクトではないと述べています。では何が正しいのでしょうか?
3 に答える
Snowbear の回答から、2 つのリストを組み合わせたより正確なイメージ (質問の最初に参照された記事で提示されたものよりも) は、次のようになります。
let FIRST = [1;2;3]
let SECOND = [4;5;6]
let COMBINED = FIRST @ SECOND
ref
F#リストは、それらの要素への参照(F#と混同しないでください)を保持します。リスト操作はそれらの参照(ポインター)をコピーしますが、要素自体はコピーしません。
既存のリストにアイテムを追加する方法は2つあります。そのため、記事間に不一致があるように見えます(どちらも正しいように見えますが)。
- 短所演算子(
::
):短所演算子は、F#リストの前に1つの項目を追加して、新しいリストを作成します。O(1)
新しいリストを作成するために非常に単純なコンストラクターを呼び出すだけでよいため、非常に高速です( )。 - 追加演算子(
@
):追加演算子は、2つのF#リストを一緒に追加して、新しいリストを作成します。O(n)
結合されたリストの要素が正しく順序付けられるためには、演算子の左側にあるリスト全体をトラバースする必要があるため、それほど速くはありません(したがって、コピーはそのリストの最初の要素から開始できます)。 )。左側のリストが非常に小さいことがわかっている場合は、これが本番環境で使用されていることを確認できますが、一般に、を使用するとパフォーマンスが大幅に向上します::
。
関数の世界では、リストは不変です。これは、元のリストが変更されないため、ノード共有が可能であることを意味します。最初のリストは空のリストで終わるため、最後のノードが 2 番目のリストを指すようにするには、そのノードをコピーする必要があります。
このステートメントを意味する場合、答えは非常に単純なようです。最初の記事の著者は、リスト ノード要素について話しているときにnodes
. ノード要素は、リスト項目自体と同じではありません。最初の記事の写真を見てください。すべての要素から次のノードに向かう矢印があります。これらの矢印はポインターです。しかし、(リストに入れられる)整数型にはそのようなポインタはありません。おそらく、list node
これらの整数をラップしてポインターを格納するタイプがあります。作成者が、nodes must be copies
これらのラッパーがコピーされていることについて話していると言ったとき。基になるオブジェクト (この場合のように値型でない場合) は複製されず、新しいラッパーは以前と同じオブジェクトを指します。