2012-02-24 2 views
2
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! 

Но здесь, < метод не те виды методов, которые не требуют никаких аргументов в порядке?

Можете ли вы указать мне, что это за использование?

+0

Возможный дубликат [Краткая нотация для одиночной анонимной функции arg (избегая подчеркивания) не работает должным образом] (http://stackoverflow.com/questions/6593277/concise-notation-for-single-arg-anonymous-function- avoiding-underscore-not-wor) –

+0

Я не думаю, что это дубликат. Связанный вопрос связан с различными вариантами синтаксиса для функций, который обращается в другую сторону, приводя к данной синтаксической ошибке. – Frank

ответ

1

То, что происходит это ЭТА расширения (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.< 
       ^

Как вы можете видеть, есть несколько implicts определены, которые превращают 3 в объект класса, который определяет метод <. Так что это работает в принципе, но не может стоять на своих собственных. Однако он работает, если у вас больше информации о типе, например, в вашем примере.

Контраст это следующим:

scala> <(3) 
<console>:8: error: not found: value < 
       <(3) 
      ^

Здесь вы можете увидеть компилятор ищет автономный < где-то. Обратите внимание, что в сообщении об ошибке указано значение, но это все равно означает, что это может быть функция, так как тип значения может быть (Int, Int) => Boolean или что-то в этом роде.

+0

Итак, почему вы можете вызывать метод без аргументов типа '2. <' и почему это эквивалентно '2 <'? в любом случае, если это формальное использование адреса? Почему я не могу вызвать свой метод с пустыми аргументами? – Sawyer

+0

в этом контексте scala позволяет вам писать '(x: Int) => 2 < x', 'x => 2. <(x)', '2.. <(_)', '2 <_',' 2. <'или просто' 2 <'. Во всех этих случаях scala создаст анонимную функцию __function__ типа 'Int => Boolean', которая вызывается при вызове __method__' <'. – incrop

+0

@incrop, ваша ссылка в другом сообщении отвечает на вопрос, почему '_' можно опустить, но синтаксис' 2. <'не соответствует синтаксическому правилу. Если вы можете вызвать метод, подобный этому, это означает, что у него нет никаких аргументов, и он не вызывает побочных эффектов, таких как s.toString, если только я не вижу, что это использование является официальным адресом где-то. – Sawyer

1

2.<относится к методу < объекта 2, тогда как 2.<(_) возвращает новую функцию с одним аргументом.Последний является ярлыком для (расширяется до) (x: Int) => 2 < x, где тип Int был выведен компилятором scala из типа элементов alist.

> 3 в вашем случае не относится ни к каким методам или объектам какого-либо объекта. > является юридическим идентификатором scala (для метода, функции или объекта), но 3 не является юридическим идентификатором (он начинается с цифры). > a может быть ссылкой a объекта > (>.a). Но ни один из них не существует в вашем примере. _ > 3 однако возвращает новую функцию с одним аргументом, который вы также могли бы написать (x: Int) => x > 3.

Это по сути то же самое, что и ответ Дэниела Собрана и комментарий Интропа к ответу Фрэнка, но менее формальный и с большим количеством примеров. Надеюсь, это поможет получить интуицию.

+0

спасибо, я понял это сейчас. – Sawyer

Смежные вопросы