2011-10-18 11 views
4

私は不変のスタックのためのScalaDocは、次のシグネチャを持つメソッドの先頭に追加を参照していることに気づい:スタックは、ELEMの型パラメータ(そのタイプで共変であるため、メソッドのシグネチャは私に間違って見えたscala.collection.immutable.Stack。+ :(前置)で何が起こっていますか?

class Stack[A+] ... 
    def +: (elem: A): Stack[A] 

べきコンパイラエラーです)。さらに、Scaladocはこのメソッドの定義がGenSeqLikeにあると言いますが、そこには存在しません。

SeqLikeには、+が実装されています。これは、Stackによって使用されているものと想像してください。

trait SeqLike[+A, +Repr] ... 
    def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That = { 
    val b = bf(repr) 
    b += elem 
    b ++= thisCollection 
    b.result 
    } 

これはStack.pushほど効率的ではありません。

+ :(プッシュとして)独自の実装を提供しようとすると、オーバーライドしているメソッドが存在しないことと、共分散の問題について予想されるコンパイラエラーが発生します。

class Stack2[+A] extends Stack[A] { 
    override def +: (elem: A): Stack[A] = this push elem 
} 

scalac Stack2.scalaができます:効率的にプッシュを使用して:

Stack2.scala:4: error: method +: overrides nothing 
    override def +: (elem: A): Stack[A] = this push elem 
      ^
Stack2.scala:4: error: covariant type A occurs in contravariant position in type A of value elem 
    override def +: (elem: A): Stack[A] = this push elem 
       ^
two errors found 

はそれが+実装することは可能ですか?

答えて

7

ドキュメントは少し混乱しています。そのメソッドはユースケースとマークされています。実際の署名は、このいずれかになります。

def +: [B >: A, That] (elem: B)(implicit bf: CanBuildFrom[Stack[A], B, That]): That 
Prepends an element to this immutable stack 

ユースケースがちょうどそれゆえ、あなたがそれを使用するかもしれない(とSeqLikeに変更し、実際の署名、ユースケースがGenSeqLikeから変更されていないにもかかわらず、一般的な方法を示しています明らかに誤った帰属)。

+:の実装が効率的ではないことは間違いありませんが、あなたが投稿したコードではこれを確実に伝えることはできませんでした。 b ++= thisCollectionそれ以外の部分は単なるスタックであり、前面にelemを押し込むことに注意してください。しかし、それはしません。 bはフードの下のちょうどArrayBufferです。

代わりに、ドキュメントのようにリストを使用してください。

+0

ありがとう、私は[ユースケース]事について知らなかった。 –

+0

ちょうどキックのために、CanBuildFromを使ってより一般的な(実際の)メソッド定義のプリペンドをオーバーライドしようとしています。 Stack.pushを使って実装する方法がわかりません。 CanBuildFromは、ArrayBufferのような変更可能なコレクションの使用を強制しているようです。 https://github.com/steshaw/playground/commit/5f5abb9693d19663d2945815290589d8529b31fc –

+0

@スティーブンショー - それはまったく単純ではない、私は同意する。 –

関連する問題