2010-09-20 5 views
23

Я обнаружил, что у Scala всегда есть «естественное объяснение» чему угодно. Всегда что-то вроде «ohh, но это просто функция, вызываемая этим и этим объектом с этим и этим параметром». В некотором смысле, ничто на самом деле не является компилятором-магии, поскольку мы знаем его с других языков.Scala «<-» для понимания

Мой вопрос на < - оператор, используемый в следующем коде:

for(i <- 0 to 10) println(i) 

В этом примере я могу видеть это переписывается на что-то вроде:

0.to(10).foreach((i:Int)=>println(i)) 

но это не объясняет, как i был перенесен в анон ymous внутри функции foreach. В точке, где вы пишете i это не объект и еще не объявленная переменная. Итак, что это такое и как оно переносится во внутренность foreach?

Я думаю, что я, наконец, обнаружил нечто, что на самом деле компилятор волшебной

Спасибо за ваше время.

Чтобы уточнить, мой вопрос: как делает < - работа оператора в 1-й строке кода, так как я не объект, на котором она может быть вызвана как функция.

ответ

18

<- является языком -определенный ключевой символ, как и =>, но в отличие от -> (который является определенным символом). Поскольку он является частью основной грамматики Scala, его можно использовать для создания привязок (для i в вашем примере), что не может быть сделано пользовательскими конструкциями.

+0

Кажется, это ответ. Я бы предложил вам задокументировать это, если это возможно, сейчас это совершенно очевидно. – Felix

+4

@Felix: Это задокументировано в спецификации. И почти каждая книга Scala, доступная на рынке, охватывает ее. – missingfaktor

+0

О, да, я еще не получил книгу. ожидая окончательного 2,8 книги – Felix

6

В этом случае это действительно магия компилятора. Перевод из for-assrehension в формат filter/map/flatmap - это особый бит desugaring, подобно преобразованию специальных форм обновления и методов применения.

57

Чтобы увеличить ответ Дейва, вот перевод схема для «для-постижений» из спецификации Scala языка:

постижения for (enums) yield e вычисляет выражение e для каждого связывания, порожденные счетчики перечислений. Последовательность счетчика всегда начинается с генератора; за этим могут следовать дальнейшие генераторы, определения значений или охранники.

Генератор p <- e производит привязки из выражения e, который каким-то образом сопоставляется с рисунком p. Определение значения val p = e связывает имя значения p (или несколько имен в шаблоне p) с результатом вычисления выражения e. Охранник if e содержит булево выражение, которое ограничивает перечисляемые привязки.

Точный смысл генераторов и охраны определяется переводом на вызывания из четырех методов: map, filter, flatMap и foreach. Эти методы могут быть реализованы по-разному для разных типов носителей.

Схема перевода следующая. На первом этапе каждый генератор p <- e, где p не является неопровержимым (§8.1) для типа e заменяются

p <- e.filter { case p => true; case _ => false } 

Затем следующие правила применяются несколько раз, пока все постижения не были устранены.

  • для-понимания for (p <- e) yield e0 переводится на e.map { case p => e0 }.

  • A для понимания for (p <- e) e0 переведено на e.foreach { case p => e0 }.

  • A для-понимания for (p <- e; p0 <- e0 . . .) yield e00, где. , , (возможно, пустая) последовательность генераторов или охранников, переведена на:
    e.flatMap { case p => for (p0 <- e0 . . .) yield e00 }.

  • A для-понимания for (p <- e; p0 <- e0 . . .) e00 где. , , (возможно пустая) последовательность генераторов или охранников, переведена на:
    e.foreach { case p => for (p0 <- e0 . . .) e00 }.

  • Генератор p <- e с последующим щитком if g переводятся на один генератор:
    p <- e.filter((x1, . . . , xn) => g)
    где x1,. , , , xn являются свободными переменными от p.

  • Генератор p <- e с последующим определением величины val p0 = e0 переводится к следующему генератора пар значений, где x и x0 свежие имена:

    val (p, p0) <- 
        for([email protected] <- e) yield { val [email protected] = e0; (x, x0) } 
    
+1

Хорошо, я не все понял после первого чтения, но это интересно :-) Откуда у вас это получилось? – Felix

+0

@Felix: Как я сказал в верхней части ответа, это из спецификации языка (можно загрузить с сайта www.scala-lang.org) – missingfaktor