Есть ли лучший способ поднять PartialFunction в Scala? - PullRequest
3 голосов
/ 18 января 2011

Я иногда сталкиваюсь со следующей схемой, где у меня по существу есть PartialFunction[SomeType,AnotherType], и хочу трактовать его как Function[SomeType,Option[AnotherType], например:

def f(s:SomeType):Option[AnotherType] = s match {
  case s1:SubType1 => Some(AnotherType(s1.whatever))
  case s2:SubType2 => Some(AnotherType(s2.whatever))
  case _ => None
}

Есть ли способ написать вышеупомянутую функцию таким образом, чтобы избежать случая по умолчанию и обернуть результат в Some, где он определен? Лучшее, что я придумала до сих пор, это:

def f(s:SomeType):Option[AnotherType] = pf.lift(s)
def pf:PartialFunction[SomeType,AnotherType] = {
  case s1:SubType1 => AnotherType(s1.whatever)
  case s2:SubType2 => AnotherType(s2.whatever)
}

Есть ли способ сделать это без определения промежуточной функции? Я уже пробовал разные вещи в соответствии с приведенным ниже описанием, но пока не получил ничего для компиляции:

def f:Function[SomeType,Option[AnotherType]] = {
  case s1:SubType1 => AnotherType(s1.whatever)
  case s2:SubType2 => AnotherType(s2.whatever)
}.lift

Ответы [ 2 ]

6 голосов
/ 18 января 2011

condOpt в объекте scala.PartialFunction. Из скаладока:

def onlyInt(v: Any): Option[Int] = condOpt(v) { case x: Int => x }
4 голосов
/ 18 января 2011

Не столько ответ, сколько объяснение того, почему huynhjl ответ правильный ...

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

val pf: PartialFunction[SomeType,AnotherType] = {
  case s1:SubType1 => AnotherType(s1.whatever)
  case s2:SubType2 => AnotherType(s2.whatever)
}

Хотя я лично предпочитаю использовать тип ascription:

val pf = {
  case s1:SubType1 => AnotherType(s1.whatever)
  case s2:SubType2 => AnotherType(s2.whatever)
} : PartialFunction[SomeType,AnotherType]

В любом случае, вы должны указать тип ввода, поэтому вы должны дать точную подпись PartialFunction.Я знаю, что кажется, что можно сделать вывод, но, увы, это, к сожалению, не так!

Используя приписанную версию, вы можете затем определить и поднять все в одном месте:

val pf = ({
  case s1:SubType1 => AnotherType(s1.whatever)
  case s2:SubType2 => AnotherType(s2.whatever)
} : PartialFunction[SomeType,AnotherType]).lift

PartialFunction.condOpt является лучшим решением, поскольку он позволяет логическому лицу выполнять большую часть этой работы за вас, оставляя намного более чистый код:)

...