2016-07-13 8 views
3

Итак, предположим, я хочу, чтобы обеспечить «поймать всех» падают обратно на PartialFunction:Сочетайте с частично определённая функция регулярной функции

val foo: PartialFunction[Int, String] = { case 1 => "foo" } 
val withDefault = foo orElse { _.toString } 

Это не компилируется: missing parameter type for expanded function ((x$1) => x$1.toString). Это:

val withDefault = foo orElse { case x: Int => x.toString } 

не компилируется либо (такая же ошибка).

Это:

val withDefault = foo orElse { (x: Int) => x.toString } 

терпит неудачу с type mismatch; found : Int => String; required: PartialFunction[?,?]

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

val withDefault = foo orElse PartialFunction[Int, String] { _.toString } 

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

+0

http://stackoverflow.com/questions/930698/why-is-partialfunction-function-in-scala можно использовать –

ответ

2

Может быть, вам нужно applyOrElse:

val withDefault = foo.applyOrElse(_: Int, (_: Int).toString) 

Или может быть, вы хотели бы что-то вроде этого:

implicit class PartialFunToFun[A,B](val f: PartialFunction[A,B]) extends AnyVal { 
    def withDefault(bar: A => B) = f.applyOrElse[A,B](_: A, bar) 
} 

и использовать его: foo.withDefault(_.toString)(1)

Кроме того, если вы хотите получить только другой PartialFunction вы можете использовать следующий синтаксис:

val withDefault = foo.orElse[Int, String]{case x => x.toString} 
+0

Я согласен, потому что это помогает. Но, пожалуйста, см. Этот другой вопрос, который я только что написал, потому что я понял, что вопрос, который я задал здесь, не совсем то, что я хотел спросить :) http://stackoverflow.com/questions/38359522/anonymous-partialfunction-syntax – Dima

0

Ошибки, с которыми вы столкнулись в течение первых двух, не относятся к orElse. Они также возникают, когда вы пытаетесь определить одни и те же функции отдельно.

scala> { _.toString } 
<console>:12: error: missing parameter type for expanded function ((x$1: <error>) => x$1.toString) 
     { _.toString } 


scala> { case x: Int => x.toString } 
<console>:12: error: missing parameter type for expanded function 
The argument types of an anonymous function must be fully known. (SLS 8.5) 
Expected type was: ? 
     { case x: Int => x.toString } 
    ^

Для последнего, вы определяете функцию, а не частично определённой функции, что приводит к «типу несовпадению» с orElse ожидает частично определённая функция будет принята.

scala> { (x: Int) => x.toString } 
res3: Int => String = $$Lambda$1127/[email protected] 

Последнее, что я добавлю, что orElse понимается как способ объединения двух PartialFunctions. _.toString сам по себе не является PartialFunction, хотя вы можете создать PartialFunction, который его использует. Для меня это похоже на то, что вы хотите получить результат по умолчанию для всех значений, для которых foo не определен, поэтому я думаю, что вы действительно хотите applyOrElse, так как это его прецедент. See the API to learn more.

+0

Конечно. Дело в том, что когда вы определяете его отдельно, тип функции действительно неизвестен: '{_.toString}' неоднозначно, потому что '_' действительно может стоять за чем-то здесь.С другой стороны, когда вы выполняете 'foo orElse {_.toString}', единственный способ его интерпретации состоит в том, что '_' является' Int', а '{case x => x.toString}' является частичная функция. – Dima

+0

Также см. Этот вопрос: http://stackoverflow.com/questions/38359522/anonymous-partialfunction-syntax, где, я думаю, я лучше выражаю эту идею. – Dima

+0

Он по-прежнему неоднозначен, потому что точка '' 'илиElse''' заключается в создании объединения входных доменов из двух PartialFunctions. Как он может преобразовать _.toString в PartialFunction, когда входной домен не указан? Это то, что компилятор не может просто сделать. Это не просто означает, что вы имеете в виду PartialFunction, который применяется ко всем Int'aм, и я не думаю, что это должно произойти, поскольку это, кажется, лежит вне цели orElse. Результатом orElse должен быть другой PartialFunction, который по-прежнему применяется только к ограниченному входному домену. –