Оставить подчеркивание в литературе функций?
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
.
Это по сути то же самое, что Даниэль С. Собрал отвечает и компрометирует комментарий Фрэнку, но менее формальный и с большим количеством примеров. Надеюсь, что это поможет получить интуицию.