2

更新
这里的所有答案都很好,但@senia's 这样做是最直接的,不需要额外的步骤。这可能会导致错误,但是当在数百种方法中使用 Map[Symbol, T] 约定时,最好在创建映射之前进行 1 步隐式转换(避免符号映射密钥永久存储)。无论如何,这是皮条客:

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

原创
在 Maps 中使用字符串键有点困扰我,只是让我慢下来,而且,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 显式定义 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]. 只需将其保留为 a Map[Symbol, T],直到您遇到需要字符串键的 API,然后让 Scala 将其隐式转换为您想要的类型。

于 2012-04-14T03:51:49.320 回答