5

Map に似た新しいタイプの Chunk を実装しようとしています。基本的に、「チャンク」は String -> Chunk からのマッピング、または文字列そのものです。

たとえば、次のように機能する必要があります。

val m = new Chunk("some sort of value") // value chunk 
assert(m.getValue == "some sort of value")

val n = new Chunk("key" -> new Chunk("value"), // nested chunks
                  "key2" -> new Chunk("value2"))
assert(n("key").getValue == "value")
assert(n("key2").getValue == "value2")

+ 演算子が不変マップに対してどのように機能するかについて少し混乱していることを除いて、これはほとんど機能しています。

これが私が今持っているものです:

class Chunk(_map: Map[String, Chunk], _value: Option[String]) extends Map[String, Chunk] {
  def this(items: (String, Chunk)*) = this(items.toMap, None)
  def this(k: String) = this(new HashMap[String, Chunk], Option(k))
  def this(m: Map[String, Chunk]) = this(m, None)

  def +[B1 >: Chunk](kv: (String, B1)) = throw new Exception(":( do not know how to make this work")
  def -(k: String) = new Chunk(_map - k, _value)
  def get(k: String) = _map.get(k)
  def iterator = _map.iterator

  def getValue = _value.get
  def hasValue = _value.isDefined

  override def toString() = {
    if (hasValue) getValue
    else "Chunk(" + (for ((k, v) <- this) yield k + " -> " + v.toString).mkString(", ") + ")"
  }

  def serialize: String = {
    if (hasValue) getValue
    else "{" + (for ((k, v) <- this) yield k + "=" + v.serialize).mkString("|") + "}"
  }
}

object main extends App {
  val m = new Chunk("message_info" -> new Chunk("message_type" -> new Chunk("boom")))
  val n = m + ("c" -> new Chunk("boom2"))
}

また、一般的にこの実装が適切かどうかについてのコメントをいただければ幸いです。

ありがとう!

編集: 代数データ型のソリューションは優れていますが、1 つの問題が残っています。

def +[B1 >: Chunk](kv: (String, B1)) = Chunk(m + kv) // compiler hates this
def -(k: String) = Chunk(m - k) // compiler is pretty satisfied with this

ここの - 演算子は機能しているように見えますが、+ 演算子は本当に B1 型の何かを返すことを望んでいるのでしょうか (私は思います)? 次の問題で失敗します。

overloaded method value apply with alternatives: (map: Map[String,Chunk])MapChunk <and> (elems: (String, Chunk)*)MapChunk cannot be applied to (scala.collection.immutable.Map[String,B1])

Edit2: Xiefei がこの質問に答えました - マップを拡張するには + を Chunk のスーパータイプ (B1) で処理する必要があるため、これを行うにはそのための実装が必要なので、これで十分です:

def +[B1 >: Chunk](kv: (String, B1)) = m + kv

ただし、実際にそれを使用するつもりはありません。代わりに、次のようにチャンクを返す実装も含めます。

def +(kv: (String, Chunk)):Chunk = Chunk(m + kv)
4

4 に答える 4

5

代数的データ型アプローチはどうですか?

  abstract sealed class Chunk
  case class MChunk(elems: (String, Chunk)*) extends Chunk with Map[String,Chunk] {
    val m = Map[String, Chunk](elems:_*)
    def +[B1 >: Chunk](kv: (String, B1)) =  m + kv
    def -(k: String) =  m - k
    def iterator = m.iterator
    def get(s: String) = m.get(s)
  }
  case class SChunk(s: String) extends Chunk
  // A 'Companion' object that provides 'constructors' and extractors..
  object Chunk {
    def apply(s: String) = SChunk(s)
    def apply(elems: (String, Chunk)*) = MChunk(elems: _*)
    // just a couple of ideas...
    def unapply(sc: SChunk) = Option(sc).map(_.value)
    def unapply(smc: (String, MChunk)) = smc match {
      case (s, mc) => mc.get(s)
    }

  }

次のように使用できます:

val simpleChunk = Chunk("a")
val nestedChunk = Chunk("b" -> Chunk("B"))
// Use extractors to get the values.
val Chunk(s) = simpleChunk // s will be the String "a"
val Chunk(c) = ("b" -> nestedChunk) // c will be a Chunk: Chunk("B")
val Chunk(c) = ("x" -> nestedChunk) // will throw a match error, because there's no "x"
// pattern matching:
("x" -> mc) match { 
  case Chunk(w) => Some(w)
  case _ => None 
} 

抽出機能はunapply単なる提案です。うまくいけば、あなたが望むものを手に入れるまで、あなたはこの考えを台無しにすることができます。

于 2012-11-28T08:56:51.900 に答える
2

それが書かれている方法では、同時にaMapと a の両方であってはならないことを強制する方法はありません。必要な便利なメソッドをString使用して値を取得し、追加することを考えています。Either

case class Chunk(value:Either[Map[String,Chunk],String]) {
  ...
}

Chunkこれにより、を表すにキーと値のペアを追加するなどの状況で、実際に何をする必要があるかについても考える必要がありますString

于 2012-11-28T04:51:08.863 に答える
1
def +(kv: (String, Chunk)):Chunk = new Chunk(_map + kv, _value)
override def +[B1 >: Chunk](kv: (String, B1)) = _map + kv

必要なのは新しいメソッドであり、 trait+で宣言されたものも実装します。Map

于 2012-11-28T04:42:17.833 に答える
1

継承の代わりに構成を使用することを検討しましたか? したがって、Chunk が Map[String, Chunk] を直接拡張する代わりに、Chunk に Map[String, Chunk] のインスタンスを内部的に保持させ、必要な追加のメソッドを提供するか、そうでなければ内部マップのメソッドに委譲します。

于 2012-11-28T04:39:08.033 に答える