Синтаксис для частичного применения карри-функций с обратно-ассоциативной инфиксной нотацией
Другими словами, есть ли хорошая причина, почему это не должно компилироваться?
def f(xs: List[Int]) = xs.foldLeft(0) _ // OK
def f(xs: List[Int]) = (xs :\ 0) _ // OK
def f(xs: List[Int]) = (0 /: xs) _
<console>:15: error: missing arguments for method /: in trait TraversableOnce;
follow this method with `_' if you want to treat it as a partially applied function
Вот некоторые обходные пути:
def f(xs: List[Int]) = xs./:(0) _
def f(xs: List[Int]): ((Int, Int) => Int) => Int = (0 /: xs)
но мой вопрос в основном о правильном синтаксисе в целом.
2 ответа
Я исправил это только сейчас, но пока не могу проверить, потому что это требует изменения спецификации.
scala> def f(xs: List[Int]) = (0 /: xs) _
f: (xs: List[Int])(Int, Int) => Int => Int
scala> f(1 to 10 toList)
res0: (Int, Int) => Int => Int = <function1>
scala> res0(_ + _)
res1: Int = 55
Проблема состоит в том, что спецификация определяет "e1 op e2", если op является ассоциативным справа, чтобы быть { val x=e1; e2.op(x) } по причинам, которые мне не очевидны, поскольку более простой e2.op(e1) решает эту проблему среди других, например, https://issues.scala-lang.org/browse/SI-1980. Я сделаю запросы.
Похоже, ошибка компилятора. Я протестировал эти выражения на разных версиях Scala и для чего я получил:
def f(xs: List[Int]) = (0 /: xs) _
Он ведет себя одинаково для 2.9.1.final
а также 2.8.2.final
но для 2.7.7.final
выдает другое сообщение об ошибке (Iterable
против TraversableOnes
), но я думаю, что это из-за редизайна библиотеки коллекций в старых версиях.
def f(xs: List[Int]) = (0 /: xs) _
<console>:4: error: missing arguments for method /: in trait Iterable;
follow this method with `_' if you want to treat it as a partially applied function
Выражение, которое я упомянул в комментарии, ведет себя по-разному для разных версий Scala.
def f(xs: List[Int]): (Int, Int) => Int => Int = (0 /: xs)
scala 2.9.1. финал:
found : (Int, Int) => Int => Int
required: (Int, Int) => Int => Int
Действительно запутанное сообщение компилятора, определенно ошибка.
scala 2.8.2.final:
found : => ((Int, Int) => Int) => Int
required: (Int, Int) => (Int) => Int
странный =>
в начале, по сравнению с 2.7.7, конечный результат выглядит как регрессия.
scala 2.7.7.final:
found : ((Int, Int) => Int) => Int
required: (Int, Int) => (Int) => Int
found
на первый взгляд правильно, но код все еще не работает.
Я искал в scala bugtracker похожие проблемы, но не смог найти ничего подходящего. Думаю, достаточно создать заявку (или две? Похоже, эти две ошибки не связаны).