Оставить подчеркивание в литературе функций?
scala> val alist = List(1,2,3,4,5)
alist: List[Int] = List(1, 2, 3, 4, 5)
scala> alist filter { 2.< }
res2: List[Int] = List(3, 4, 5)
scala> alist filter { 2 < }
res3: List[Int] = List(3, 4, 5)
scala> alist filter { > 3 }
<console>:1: error: ';' expected but integer literal found.
alist filter { > 3 }
Почему работают { 2.< } и {2 <}? Думаю, по крайней мере, я должен написать { 2 < _ } правильно?
Метод, который не требует аргументов, вы также можете опустить точку и использовать постфиксную запись оператора:
scala> val s = "Hello, world!"
s: java.lang.String = Hello, world!
scala> s toLowerCase
res4: java.lang.String = hello, world!
Но здесь метод < - это не те методы, которые не требуют правильных аргументов?
Можете ли вы указать мне, что это за использование?
Ответы
Ответ 1
Что происходит, это расширение Eta (6.26.5):
Eta-расширение преобразует выражение типа метода в эквивалентное выражение типа функции.
В этом случае 2 < - это тип метода: (один из) метод < на Int. Однако filter ожидает тип функции. В этом случае Scala выполняет автоматическое расширение.
Обратите внимание, что, поскольку тип, ожидаемый с помощью filter, известен, он может правильно вывести метод 2 <.
Ответ 2
Причиной этого является то, что 2 является объектом, поэтому, если вы пишете 2.< или 2 < (которые на самом деле одинаковы в Scala), вы вызываете метод < на объект 2.
Если вы просто пишете < или >, компилятор будет искать такой метод в локальной области, но не найдет его. Аналогично, пишу > 3, компилятору нужен доступный метод >, который не является.
Вы также можете увидеть это поведение в консоли напрямую:
scala> 3.<
<console>:8: error: ambiguous reference to overloaded definition,
both method < in class Double of type (x: Char)Boolean
and method < in class Double of type (x: Short)Boolean
match expected type ?
3.<
^
Как вы видите, существует несколько определенных импликтивов, которые превращают 3 в объект класса, который определяет метод <. Так что это работает в принципе, но не может стоять на своих собственных. Однако он работает, если у вас больше информации о типе, например, в вашем примере.
Сравните это со следующим:
scala> <(3)
<console>:8: error: not found: value <
<(3)
^
Здесь вы можете увидеть, как компилятор ищет автономный <. Обратите внимание, что в сообщении об ошибке указано значение, но это все равно означает, что это может быть функция, поскольку тип значения может быть (Int, Int) => Boolean или что-то в этом роде.
Ответ 3
2.< относится к методу < объекта 2, тогда как 2.<(_) возвращает новую функцию с одним аргументом. Последний является ярлыком для (расширяется до) (x: Int) => 2 < x, где тип Int был выведен компилятором scala из типа элементов alist.
> 3 в вашем случае не ссылается ни на какой метод или объект какого-либо объекта. > является юридическим идентификатором scala (для метода, функции или объекта), но 3 не является юридическим идентификатором (он начинается с цифры). > a может быть ссылкой на элемент a объекта > (>.a). Но ни один из них не существует в вашем примере. _ > 3 однако возвращает новую функцию с одним аргументом, который вы также можете написать (x: Int) => x > 3.
Это по сути то же самое, что Даниэль С. Собрал отвечает и компрометирует комментарий Фрэнку, но менее формальный и с большим количеством примеров. Надеюсь, что это поможет получить интуицию.