2012-04-13 10 views
2

更新
ここではすべての回答が良いですが、@ seniaの方が、追加の手順を必要とせずに最も直接的です。これはおそらくバグにつながりますが、何百ものメソッドでMap [Symbol、T]規則を使用する場合、マップ作成の前に1ステップの暗黙の変換が優先されます(Symbol Mapキーのpermgen格納を避ける)。ただ、IMO、私を遅くしてあり、記号キーとして目にとして文法的に容易ではない
それは私にマップの文字列キーを使用してビットを気にスカラマップ、文字列への記号キーの埋め込み

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

オリジナル:いずれにせよ、ここでは売春斡旋業者です。

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

カップルの事:
1)これが正しい署名である

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

だから、私は私のかゆみを傷つけるために暗黙的に作成されましたか?上記の作品は、しかし、A <: Symbol私は、Symbolに匹敵する何かをSymbolから派生するものを意味するために取る。

2)手動でマップを入力するときはこれを使用します。すなわち便宜上のものである。私は暗黙のうちに何かの騒ぎにぶつかりますか?それは問題を引き起こさないように(例えばstring2Intのような)問題を引き起こしているようですが、何かが欠けているかどうかはわかりません。

おかげで[OK]を

EDIT
、うまく#1私は実際に代わり[A <: Symbol, B]

[Symbol, B]、私が何を意味するかと言うことができます。しかし、今、私は別の問題、シンボル対で自分自身を見つけます文字列暗黙的には、私はシンボル・キーを使用できるようにするために、すべての新しいマップ(すなわち、素晴らしいコンパイラ・タイプの推論を失う)に対してMap [String、Type]を明示的に定義する必要があります。

どのようにして、シンボルのキーをマップすることができますが、タイプシグネチャを指定しないと[String、Type]が推測されますか?つまり、私がやるとき地図[文字列、INT]推測するコンパイラを持っている:あなたは、明示的にマップのタイプを指定する必要はありません

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

hmmm、私は "A"の代わりに "Symbol"を使うことができますね;-) – virtualeyes

+0

この種の動作は他の開発者を驚かせるかもしれません。おそらく ' - >'を他の言葉に置き換えるほうがいいでしょうか?たとえば、 ': - ' 'や'〜> 'などです。 – senia

+0

私はPimp-My-Libraryパターン(正確にあなたの答えで提供されるパターンです)の文脈では、Symbol - > Typeは完璧です。 Scalaコンパイラの素晴らしい点は、混乱した人はマウスを " - >"の上に置くと、クリックして暗黙的に参照できることです。 Ruby、Groovyなどでは、明示的なドキュメンテーションがなくても謎めいた謎のツアーがはるかに多い。また、シンボルマップキーは、permgenを取ります。そのため、見かけ上の使用で眉毛(および調査)が増えるはずです。最後に、コンパイラーはMap [String、Type]を推論します。その結果、どのように起こっているのかを調べる必要があります。 – virtualeyes

答えて

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) 

このような行為は、他の開発者を驚かせることができます。たぶん->を他の言葉で置き換える方が良いでしょうか?例えば、:->または~>です。

+0

完全に病気、おや;-) pimp-my-libraryをブートするので、ケースが隔離され/安全です。あなたはこれを自分で使っているのですか?説明するための欠点/認識していることはありますか? – virtualeyes

+0

私は約2〜3週間スカラを学んでいるので、まだお気に入りのトリックはありません。私は英語のネイティブスピーカーではないので、あなたのコメントの一部を理解することは難しいです。 – senia

+0

申し訳ありませんが、 "完全に病気、男"とは、 "ありがとう、素晴らしい答え!"私はそのパターンを実装しましたが、実際には動作します。コンパイラは、署名キーを文字列として推論し、署名を指定する必要はありません。 2、3週間Scalaを勉強しているのなら印象的ですが、1年後にどこにいるのかを見たいと思っています;-) – virtualeyes

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 
} 
+0

+1、良い点は、 'キーの一部として保存されていました!それは次のビットだった、私は、ああ、いや、私は明示的に目的を破るようなマップシグネチャを打ち出さなければならないことに気づいた。とにかく、シンボルキーを使用するときにコンパイラにMap [String、Type]を推論させるには? – virtualeyes

+0

別のMap.applyに興味があります。 pimp-my-libraryの素晴らしい点は、パッケージオブジェクトに暗黙的にドロップすることができ、インポートを行う必要がないことです。 – virtualeyes

+0

@virtualeyesこの 'Map2'はあなたのパッケージにも定義することができるので、implicitsを使うことには不利ではありません。 @ seniaの答えでは、Predef for Symbolsの暗黙の 'any2ArrowAssoc'を静かにオーバーライドしています。これは、あなたがそれを忘れた場合にバグにつながる可能性があります。 –

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[String, T]Map[Symbol, T]を変換するタイプを指定する必要はありません。文字列キーが必要なAPIを使用するまではMap[Symbol, T]のままにしておき、Scalaが暗黙的に必要な型に変換させるようにしてください。

+0

良い点、これを試してみてください...。 – virtualeyes

+0

それは私が望むものではありません;-)おそらくマイナーな問題ですが、Map Symbolのキーはpermgenを取ります。 @ seniaのソリューションは、Mapを作成する前(または作成中)にSymbolからStringへの変換を行い、Map [String、T]を結果として返します。また、作成後のマップを手動で変換したくないのは間違いありません。私はMap [Symbol、T]のコンベンションを何百ものコントローラメソッドで使用していますが、実際のタイプを指定する必要がありません。私たちが見ると、string2Intやその他の保証されたfuture-bugよりバグのように見えるかもしれません。 – virtualeyes

+0

@virtualeyes PermGenの問題全体については不明です。シンボルはPermGenに保存されていますか?地図を表示する前のコンバージョンはどのように役立ちますか?実数型の指定については、決して行う必要はありません。回答を更新します。 – leedm777

関連する問題