リストの + 演算子が Scala で廃止されるのはなぜですか?
http://www.scala-lang.org/docu/files/api/scala/List.html#%2B%28B%29
リストの + 演算子が Scala で廃止されるのはなぜですか?
http://www.scala-lang.org/docu/files/api/scala/List.html#%2B%28B%29
良い質問なので、Odersky らの本で調べました。それは次のように述べています(ここでこれを引用することは著作権侵害ではないことを願っています;-)):
List
リストへの追加にかかる時間はリストのサイズに比例して増加するのに対し、先頭への追加には一定の時間がかかるため、クラスは追加操作を提供しません::
。要素を追加してリストを作成する場合のオプションは、要素を先頭に追加することです。終了したら、reverse
;を呼び出します。またはListBuffer
、追加操作を提供する可変リストである を使用し、完了したら を呼び出しますtoList
。
私が FP を理解している限り、少なくとも純粋な関数型言語では、リストの先頭に追加することは追加するよりもはるかに一般的です。Scala の設計者は+
、 を使用して追加することに慣れている Java 開発者の便宜のために演算子を追加しadd()
、それについて考え直したとしか思えません。
2008 年 5 月のリビジョン 15071で廃止され、次のメッセージが表示されました。
問題のある + メソッドをすべて廃止し、リリースに登場しなかったメソッドを削除しました。
これは、StringAdd#+ のあいまいさを避けるためだったと思います。以下の 2.7.6 と 2.8.0 Beta の違いを比較してください。
Welcome to Scala version 2.7.6.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_15).
Type in expressions to have them evaluated.
Type :help for more information.
scala> List(1) + 2
warning: there were deprecation warnings; re-run with -deprecation for details
res0: List[Int] = List(1, 2)
scala> List(1) + "2"
warning: there were deprecation warnings; re-run with -deprecation for details
res1: List[Any] = List(1, 2)
2.8 では、メソッドが削除され、次のようになります。
Welcome to Scala version 2.8.0.Beta1-RC8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_15).
Type in expressions to have them evaluated.
Type :help for more information.
scala> List(1) + 2
<console>:5: error: type mismatch;
found : Int(2)
required: String
List(1) + 2
^
scala> List(1) + "2"
res1: java.lang.String = List(1)2
アップデート
scala-user リストについて、Martin Odersky 氏は次のように述べています。
List#+ の本当に悪い点を見つけるには、次のようにすると何が期待できるかを考えてみてください。
List(1, 2, 3) + "が正しい結果"
?
oxbow_lakes が追加-この不可解なコメントを解凍するのにしばらく時間がかかりましたが、要点は、演算子によって暗示された型の可換性に違反することだと思います+
。つまり、 の型は の型a + b
と同じでなければなりません。b + a
UPDATE Martin Odersky の説明:
あなたは何を期待しますか
List(1, 2, 3) + "が正しい結果"
生産する?「List(1, 2, 3) が正しい結果です」という文字列が期待されます。
2.7 スタイルの List.+ では、代わりに List[Any], List(1, 2, 3, "is the correct result") を取得します。
私はそれを悪い驚きと分類します。要約すると、要素の型が共変であるコレクションに対して + メソッドを使用するべきではありません。セットとマップは非バリアントであるため、 + メソッドを持つことができます。それはすべてかなり繊細で厄介です。Java の + を文字列の連結に使用しようとしない方がよいでしょう。しかし、Scala が設計されたときのアイデアは、基本的にすべての Java 式構文 (String + を含む) を保持することでした。そして、今それを変えるには遅すぎます。
それは交換可能ではなく、特にリストでは最適ではありませんでした。さらに、可変コレクションと不変コレクションでは動作が異なります。Scala 2.8 では、次のようになります。
element +: sequence // prepend
sequence :+ element // append
sequenece ++ sequence // concatenate
可変/不変のものは完全には解決されていません。最初のステップとして一連のメソッドが非推奨になりましたが、最初に非推奨期間がなければ、それらを変更したり、完全に削除したりすることはできません。
このスレッドをたどると、おそらくパフォーマンスの問題であることがわかります。
List
一般に、追加しないように構成を調整する必要があります。Scala の List は不変の単一のリンクされたリストであるため、その末尾への追加は O(n) 操作です。
ListA ::: ListB
は右結合であり、ListA の長さに比例して時間内に実行されます ' ' は時間a ::: b
内に実行される /prepend/ 操作ですO(a.length)