Scala - добавить неприменить в Int - PullRequest
8 голосов
/ 15 марта 2012

Я хочу быть в состоянии сделать это:

scala> val Int(i) = "1"
i: Int = 1

Но Int не имеет unapply метода.

Я нашел этот ответ , который дает инструкции о том, как неявно добавить метод к существующему объекту, поэтому я попробовал его.Решение, которое они дали, работает, но, к сожалению, не для сопоставления с образцом.Вот что у меня есть:

object UnapplyInt {
  val IntRE = """^(\d+)$""".r
  def unapply(v: String): Option[Int] = v match {
    case IntRE(s) => Some(s.toInt)
    case _ => None
  }
}
implicit def int2unapplyInt(objA: Int.type) = UnapplyInt

Все эти тестовые примеры в порядке:

val UnapplyInt(i) = "1"       // pattern matching with unapply is fine
val i = Int.unapply("1").get  // implicit conversion is fine

Но тот, который я хочу, терпит неудачу:

scala> val Int(i) = "1"
<console>:10: error: object Int is not a case class constructor, nor does it have an unapply/unapplySeq method
       val Int(i) = "1"
           ^

Если неявное преобразованиеработает и сопоставление с шаблоном unapply работает, почему Scala не объединяет эти две вещи для неявного сопоставления с образцом?

1 Ответ

8 голосов
/ 16 марта 2012

edit Так что мои первоначальные рассуждения были бесполезны. Настоящая причина взята из Раздела 8.1.8 спецификации языка Scala

Syntax:
    SimplePattern ::= StableId ‘(’ [Patterns] ‘)’

То есть объект-экстрактор должен быть стабильным, а неявное преобразование - нестабильным. Нет объяснения, почему экстрактор должен быть стабильным; Я подозреваю, что это потому, что Scala не хочет рассматривать экстрактор как выражение , потому что это может быстро стать неоднозначным:

... match {
    foo(bar)(baz)
}

Теперь, кто конструктор и какие переменные шаблона?

К счастью, вы можете сделать это, и все работает отлично (хотя, как вы прокомментировали, возникают другие проблемы):

object Int {
    def unapply(v: String) = try Some(v.toInt)
        catch { case _: NumberFormatException => None }
}

val Int(i) = "5"

, поскольку тип Int и объект Int находятся в разных пространствах имен.

...