Оставить подчеркивание в функции буквальным?
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!
Но здесь, <
Метод это не те методы, которые не требуют аргументов, верно?
Можете ли вы указать мне, что это за использование?
3 ответа
Происходит расширение Eta (6.26.5):
Эта-расширение преобразует выражение типа метода в эквивалентное выражение типа функции.
В этом случае, 2 <
это тип метода: (один из) метод <
на Int
, Тем не мение, filter
ожидает тип функции. В таком случае Scala выполняет автоматическое расширение eta.
Обратите внимание, что, поскольку тип, ожидаемый filter
известно, что он может правильно сделать вывод, что 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
или что-то типа того.
2.<
относится к методу <
объекта 2
, в то время как 2.<(_)
возвращает новую функцию с одним аргументом. Последний является сокращением для (расширен до) (x: Int) => 2 < x
где тип Int
был выведен компилятором Scala из типа элементов alist
,
> 3
в вашем случае не ссылается на какой-либо метод или объект какого-либо объекта. >
является допустимым идентификатором scala (для метода, функции или объекта), но 3
не является юридическим идентификатором (начинается с цифры). > a
может быть ссылкой на член a
объекта >
(>.a
). Но ни один из них не существует в вашем примере. _ > 3
однако возвращает новую функцию с одним аргументом, который вы также можете написать (x: Int) => x > 3
,
По сути, это то же самое, что ответ Даниэля С. Собрала и комментарий к ответу Фрэнка, но менее формальный и с большим количеством примеров. Надеюсь, что это помогает получить интуицию.