2014-10-25 3 views
0

난 부울 및 문자열을 사용한 혼합지도 만들 때 :가장 좋은 방법

scala> val map = Map('boolean -> true, 'string -> "string") 
map: scala.collection.immutable.Map[Symbol,Any] = Map('boolean -> true, 'string -> string) 

을 그리고 내가 얻을 직접 부울 부분에 액세스하려고 : 번째 수행이지도를 만들 수있는 방법이 있나요

scala> implicit def anyAsBoolean(x: Any) = x.asInstanceOf[Boolean] 
warning: there were 1 feature warning(s); re-run with -feature for details 
anyAsBoolean: (x: Any)Boolean 

scala> if (map('boolean)) true else false 
res3: Boolean = true 

:

scala> if (map('boolean)) true else false 
<console>:9: error: type mismatch; 
found : Any 
required: Boolean 
       if (map('boolean)) true else false 
        ^

그래서 나는 그 일을하기 위해 암시를 정의해야 클라이언트 코드에 암시 적 부분을 추가 할 필요없이 암시 적으로 변환합니까?

+0

정말 이런 식으로해서는 안됩니다. 언젠가 당신이''boolean'에 부울을 넣는 것을 잊으면 어떻게 될까요? 런타임 오류가 발생합니다. 데이터가 실제로 무엇인지 유형을 반영하도록하십시오! 문자열이나 파일 등에서 데이터를 읽어야 할 경우 match 문 사용 방법을 확인하고 발생하는 모든 오류를 처리하십시오. –

+0

심볼 이름이 그 예입니다. 요점은 내 맵에''symbol -> true'를 놓고 다른 타입을 가리키는 다른 심볼들이 있다면,''map ('symbol)'을 타입 캐스팅없이 boolean으로 사용할 수 있기를 원합니다. 클라이언트 코드. – DavidG

답변

0

그래서 나는 Map[Symbol, Any]에서 상속 받고 다음과 같이 추출을 수행했다 :

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

object OptionMap { 
    def apply(options_map: Map[Symbol, Any]) = new OptionMap(options_map) 

    def apply(kv: (Symbol, Any)*) = new OptionMap(kv.toMap) 
} 

class OptionMap(options_map: Map[Symbol, Any]) extends Map[Symbol, Any] { 

    def apply[T](name: Symbol) : T = options_map(name).asInstanceOf[T] 

    def get[T](name: Symbol) : T = options_map(name).asInstanceOf[T] 

    def get(name: Symbol) : Option[Any] = options_map.get(name) 

    override def contains(name: Symbol): Boolean = options_map.contains(name) 

    def +[B1 >: Any](kv: (Symbol, B1)): OptionMap = OptionMap(options_map + kv) 

    def -(key: Symbol): OptionMap = OptionMap(options_map - key) 

    def iterator = options_map.iterator 
} 

// Exiting paste mode, now interpreting. 

defined module OptionMap 
defined class OptionMap 

scala> val omap = OptionMap('boolean -> true, 'string -> "string", 'int -> 5, 'double -> 3.14) 
omap: OptionMap = Map('boolean -> true, 'string -> string, 'int -> 5, 'double -> 3.14) 

scala> if(omap.contains('boolean) && omap('boolean)) true else false 
res0: Boolean = true 

scala> omap[String]('string) + " world!" 
res1: String = string world! 

scala> omap[Int]('int) + 3 
res2: Int = 8 

scala> omap[Double]('double) + 3 
res3: Double = 6.140000000000001 

scala> omap + ('extra -> true) 
res4: OptionMap = Map('string -> string, 'double -> 3.14, 'boolean -> true, 'int -> 5, 'extra -> true) 

scala> omap - 'extra 
res5: OptionMap = Map('boolean -> true, 'string -> string, 'int -> 5, 'double -> 3.14) 

이제 내가 원했던 것을 클라이언트 코드에 암시 할 필요가 없습니다. 물론 클라이언트는 각 key -> value 쌍에 저장된 유형을 알아야하지만 그럴 수 있습니다.

4

당신은 ShapelessHMap 시도 할 수 있습니다 :

class BiMapIS[K, V] 
implicit val intToString = new BiMapIS[Int, String] 
implicit val stringToInt = new BiMapIS[String, Int] 

val hm = HMap[BiMapIS](23 -> "foo", "bar" -> 13) 
//val hm2 = HMap[BiMapIS](23 -> "foo", 23 -> 13) // Does not compile - strong type 

scala> hm.get(23) 
res0: Option[String] = Some(foo) 

scala> hm.get("bar") 
res1: Option[Int] = Some(13) 

그래서, 클라이언트가 어떤 암시 convertions을 명시 적으로지도를 캐스팅하거나 작성할 필요가 없습니다 (intToString는 stringToInt지도의 정의에만 필요). HMap의 유형은 {Int -> String, String -> Int}으로 제한되며 {String -> A; String -> B}도 할 수 없으므로 가능한 경우 문자열을 일부 대/소문자로 교체해야합니다.

map('boolean).asInstanceOf[Boolean] 

아니면 유형의 정보를 유지하는 Either을 사용할 수 있습니다 :

3

왜 거기 캐스팅하지 않는 사용

val map: Map[Symbol, Either[Any, Boolean]] = Map(
    'boolean -> Right(true), 
    'string -> Left("string")) 

map('boolean).fold(throw new IllegalStateException(_), b => b) 

을 Scalaz :

val map: Map[Symbol, Either[Any, Boolean]] = Map(
    'boolean -> true.right[Any], 
    'string -> "string".left[Boolean]) 

map 'boolean | throw new IllegalStateException 
+0

감사합니다. 유형 캐스팅에 대해 알고 있지만 클라이언트 측에서 많은 작업이 필요하다고 느끼고 있습니다. 그래서 피하려고합니다. 단지 그것을 필요로하지 않는 이질적인 맵을 갖는 쉬운 방법이 있는지 알고 싶을뿐입니다. – DavidG

+0

@DavidG 내가 쓴 것처럼 타입 캐스팅을 원하지 않는다면 '어느 쪽이든'을 사용하십시오. 효율성에 대해 이야기하는 경우 입력 유형이 가장 빠릅니다 (나는 확신 할 수 없습니다). 나는 항상 전통적인 방법으로 해결하려고 노력한다. 그래서 그것은 작은 것들에 대한 유지자를 혼동하지 않는다. –