更新
这里的所有答案都很好,但@ senia的答案最直接,不需要额外的步骤。这可能会导致错误,但是当在数百种方法中使用Map [Symbol,T]约定时,首先在地图创建之前进行一步隐式转换(避免符号映射键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
我的意思是,从符号与等于符号的东西派生的东西。
2)当我手动输入地图时,我会使用它;即为方便起见。我是否会用这种隐含的方式遇到任何障碍?似乎边缘情况不足以导致问题(例如string2Int),但不确定我是否遗漏了某些东西。
由于
修改
好吧,好吧#1我实际上可以说出我的意思,[Symbol, B]
而不是[A <: Symbol, B]
但是现在我发现自己有另一个问题,符号到字符串的隐式将我置于各种角落,因为我必须为所有新映射显式定义Map [String,Type](即丢失了不错的编译器类型)推理)以便能够使用符号键。
如何在不指定类型签名时获得两个世界中最好的地图符号键,但推断出[String,Type]?即,当我这样做时,让编译器推断Map [String,Int]:
val map = Map('foo -> 1)
答案 0 :(得分: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)
这种行为可能让其他开发者感到惊讶。也许用其他词替换->
会更好吗?例如:->
或~>
。
答案 1 :(得分: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
}
答案 2 :(得分: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]
的类型。只需将其保留为Map[Symbol, T]
,直到您点击需要字符串键的API,然后让Scala隐式将其转换为您想要的类型。