2

更新
ここではすべての答えが適切ですが、@ seniaは、追加の手順を必要とせずに、最も直接的にそうします。これはバグにつながる可能性がありますが、何百ものメソッドでMap [Symbol、T]規則を使用する場合は、マップ作成前の1ステップの暗黙的な変換が推奨されます(Symbol Mapキーのpermgenストレージを回避します)。とにかく、ここにポン引きがあります:

class SymbolProvidesPair(i: Symbol) { def ->[T](s: T) = (i.toString.tail, s) }
@inline implicit def symbol2String(i: Symbol) = new SymbolProvidesPair(i)

オリジナル
マップで文字列キーを使用するのは少し面倒ですが、速度が遅くなり、IMOであり、記号キーほど構文的に簡単ではありません。

val map: Map[String, Int] = Map("strings" -> 1, "blow" -> 2)
val map: Map[String, Int] = Map('symbols -> 1, 'rock -> 2)

だから、私は私のかゆみを掻くために暗黙的に作成しました:

implicit def symbolKey2String[A <: Symbol, B](x:(A,B)) = (x._1.toString, x._2)

いくつかのこと:
1)これは正しい署名ですか?上記は機能しますが、A <: Symbol私は、Symbolから派生したものとSymbolに等しいものを意味します。

2)手動でマップを入力するときにこれを使用します。つまり、便宜上です。私はこの暗黙の問題で何かを打つつもりですか?問題(たとえば、string2Intなど)を引き起こさないのに十分なエッジケースのようですが、何かが足りないかどうかはわかりません。

ありがとう

編集
わかりました、まあ#1私は実際に私が意味することを言うことができ[Symbol, B]ます[A <: Symbol, B]

しかし今、私は別の問題に気づきました。シンボルから文字列への暗黙のボックスは、すべての新しいマップに対してMap [String、Type]を明示的に定義する必要があるため、ある種の隅に私を閉じ込めます(つまり、優れたコンパイラ型推論を失います)。シンボルキーを使用できるようにするため。

それでは、型署名を指定しない場合に[String、Type]を推測して、両方の世界、地図記号キーを最大限に活用するにはどうすればよいでしょうか。つまり、次の場合にコンパイラにMap [String、Int]を推測させます。

val map = Map('foo -> 1)
4

3 に答える 3

2

マップのタイプを明示的に指定する必要はありません:

scala> class SymbolToPait(i: Symbol) { def ->[T](s: T) = (i.toString().tail, s)}
defined class SymbolToPait

scala> implicit def symbolToPair(i: Symbol) = new SymbolToPait(i)
symbolToPair: (i: Symbol)SymbolToPait

scala> 'Symbol -> "String"
res0: (String, String) = (Symbol,String)

scala> Map('Symbol -> "String")
res1: scala.collection.immutable.Map[String,String] = Map(Symbol -> String)

scala> Map('Symbol -> 1)
res2: scala.collection.immutable.Map[String,Int] = Map(Symbol -> 1)

この種の動作は、他の開発者を驚かせる可能性があります。->他の言葉に置き換えた方が良いのではないでしょうか?たとえば、:->または~>.

于 2012-04-13T17:05:43.050 に答える
2

ご指摘のとおり、必要ありませんA。おそらく最初の文字も削除したいと思うでしょう。'

implicit def symbolKeyToString[B](x: (Symbol, B)) = (x._1.toString.tail, x._2)

問題点については、毎回マップの署名を入力する必要があり、キーにスペースや演算子文字を含めることはできません。これは自分でやるものではない…

編集:毎回署名を入力したくない場合は、代わりにMap.apply暗黙を使用して忘れてください:

object Map2 {
  def apply[B](xs: (Symbol, B)*) = 
    xs map {case (k, v) => (k.toString.tail, v)} toMap
}
于 2012-04-13T17:07:04.463 に答える
1

現在の解決策についていくつか警告があります。

まず第一に、あなたは の意味を変えており'sym -> x、それは とは別のものを意味し('sym, x)ます。これは紛らわしいと思います。

また、この変換を使用するコードと実際に必要なコードを混在させることも困難になりますMap[Symbol, _]

シンボルをマップに入れる前に文字列に変換する代わりに、マップを変換することをお勧めします。私にははるかに簡単に思えます。

scala> implicit def symMap2strMap[T](m: Map[Symbol, T]): Map[String, T] = m.map {
     |   case (key, value) => key.toString.tail -> value
     | }
symMap2strMap: [T](m: Map[Symbol,T])scala.collection.immutable.Map[String,T]

scala> val sym = Map('foo -> 1, 'bar -> 2)
sym: scala.collection.immutable.Map[Symbol,Int] = Map('foo -> 1, 'bar -> 2)

scala> sym: Map[String, Int]
res0: Map[String,Int] = Map(foo -> 1, bar -> 2)

編集

Map[Symbol, T]に明示的に変換する型を指定する必要はありませんMap[String, T]。文字列キーを必要とする API にヒットするまではそのままにしてMap[Symbol, T]おき、Scala に暗黙的にそれを必要な型に変換させます。

于 2012-04-14T03:51:49.320 に答える