Можно ли использовать неявные преобразования для параметров в экстракторы (не применять) в Scala? - PullRequest
1 голос
/ 30 ноября 2009

Я создал класс CaseInsensitive, который переносит строку (см. Реализация класса строки, который выполняет сравнения без учета регистра в Scala ).

Я создал класс case, который имеет переменную-член типа CaseInsensitive, поэтому он получает метод по умолчанию unapply, который извлекает переменную типа CaseInsensitive, но я надеялся использовать его следующим образом:

case class PropertyKey( val name : CaseInsensitive )

val foo = new PropertyKey("foo")
val result = foo match {
  case PropertyKey("foo") => true
  case _ => false
}

Этот код не компилируется: (в строке экстрактора, а не в строке конструктора)

type mismatch;
 found   : java.lang.String("foo")
 required: com.acme.CaseInsensitive 

Но я думал, что мои неявные преобразования из String в CaseInsensitive позволят это скомпилировать, вместо того, чтобы мне приходилось вводить более подробное:

case class PropertyKey( val name : CaseInsensitive )

val foo = new PropertyKey("foo")
val result = foo match {
  case PropertyKey(CaseInsensitive("foo")) => true
  case _ => false
}

Вот реализация CaseInsensitive:

/** Used to enable us to easily index objects by string, case insensitive
 * 
 * Note: this class preserve the case of your string!
 */
case class CaseInsensitive ( val _s : String ) extends Proxy {
  require( _s != null)

  val self = _s.toLowerCase
  override def toString = _s

  def i = this // convenience implicit conversion
}

object CaseInsensitive {
  implicit def CaseInsensitive2String(c : CaseInsensitive) = if ( c == null ) null else c._s
  implicit def StringToCaseInsensitive(s : String) = CaseInsensitive(s)

  def fromString( s : String ) = s match {
    case null => None
    case _ => Some(CaseInsensitive(s))
  }
}

1 Ответ

4 голосов
/ 30 ноября 2009

Вы всегда можете определить удобный экстрактор и импортировать его (не стесняйтесь использовать более короткое имя):

object PropertyKeyCI {
  def unapply(p: PropertyKey): Option[String] = Some(p.name.self)
}

Тогда извлечение составляет:

  val foo = new PropertyKey("foo")
  val result = foo match {
    case PropertyKeyCI("foo") => true
    case _ => false
  }

(оповещение о плохой семантике)

Хотя обратите внимание, что для PropertyKeyCI ("Foo") это будет соответствовать значению false, поскольку ваш класс "CaseInsensitive" действительно является классом "LowerCase". Я говорю это потому, что мне трудно представить, каким будет желаемое поведение метода unapply () в противном случае. Из класса по умолчанию для вашего дела вы возвращаете Option [String] исходной (unercercased) строки, которая дает неинтуитивное поведение:

  // result == false !!!!
  val foo = new CaseInsensitive("Foo")
  val result = foo match {
    case CaseInsensitive("foo") => true
    case _ => false
  }
  val CaseInsensitive(s) = "aBcDeF"
  assertFalse(s == "abcdef")

Ауууу .... брось это. Просто используйте DOS.

...