Синтаксис для частичного применения карри-функций с обратно-ассоциативной инфиксной нотацией

Другими словами, есть ли хорошая причина, почему это не должно компилироваться?

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 похожие проблемы, но не смог найти ничего подходящего. Думаю, достаточно создать заявку (или две? Похоже, эти две ошибки не связаны).

Другие вопросы по тегам