Отправка сообщений функциям в Scala

Я работаю над книгой Брюса Тейта Семь языков за семь недель. и мне трудно понять его реализацию sizer.scala (Scala: день 3). В частности, рассмотрим следующий объект Singleton

object PageLoader {
    def getPageSize(url : String) = Source.fromURL(url).mkString.length
}

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

def getPageSizeConcurrently() = {
    val caller = self

    for(url <- urls) {
        actor { caller ! (url, PageLoader.getPageSize(url)) }
    }

    for(i <- 1 to urls.size) {
        receive {
            case (url, size) =>
                println("Size for " + url + ": " + size)
        }
    }
}
  1. К чему относится self? getPageSizeConcurrently? Может ли self ссылаться на функцию?
  2. Предполагая, что self делает ссылку на getPageSizeConcurrently, считается ли это довольно стандартным в мире Scala? Зачем отправлять сообщения функции, а не объекту или наоборот?

ОБНОВЛЕНИЕ: рассматриваемый код использует self только один раз, но он начинается со следующих операторов import.

import scala.io._
import scala.actors._
import Actor._

Просматривая API Scala, оказывается, что объект Actor singleton имеет self метод. Даже если это self назначено caller, я не понимаю, почему должен выполняться блок receive.


person Chris Frederick    schedule 19.07.2011    source источник
comment
Какой класс или объект имеет getPageSizeConcurrently в качестве одного из своих методов?   -  person Rex Kerr    schedule 19.07.2011
comment
@Rex Ничего, насколько я могу судить. Я пропустил несколько других методов (и определение urls) здесь, но в остальном это дословно из книги. Единственный класс или объект, объявленный в коде, — это PageLoader, как показано выше.   -  person Chris Frederick    schedule 19.07.2011


Ответы (3)


В объекте-компаньоне Актера есть метод self. Из scaladoc:

Возвращает исполняемого в данный момент актера. Следует использовать вместо этого во всех блоках кода, исполняемых акторами.

Я предполагаю, что ваш код импортировал объект Актера, и что это метод self для объекта Актера, который вызывает ваш код. Таким образом, вы получаете ссылку на основную ветку акторов, в которой вы находитесь, а анонимные акторы, для которых вы начинаете получать размер страницы, могут отправить сообщение обратно в ветку, в которой вы находитесь.

person Jostein Stuhaug    schedule 19.07.2011
comment
Интересный! Итак, есть ли разница между основным потоком актора, возвращаемым методом self Актера, и анонимными актерами в приведенном выше коде? Я бы подумал, что исполняющий в настоящее время актер на самом деле будет одним из анонимных актеров, которые были начаты... - person Chris Frederick; 19.07.2011
comment
Нет, нет никакой разницы, но в то время, когда вы вызываете self, исполняемый в данный момент актор является основным потоком актор. Так вот на что ссылается вызывающий объект позже, когда вы используете его при создании анонимных акторов. - person Jostein Stuhaug; 19.07.2011
comment
Ах, конечно, это имеет смысл. Итак, следующие вызовы receive неявно вызываются в основном потоке актора, верно? - person Chris Frederick; 19.07.2011
comment
Я не думаю, что правильно говорить, что вызывается неявно, поскольку это может быть истолковано как неявное в особом смысле этого слова в scala. receive — это обычный вызов метода, такой же, как и self, и он вызывается в том же основном потоке, да. - person Jostein Stuhaug; 24.07.2011

self не является ключевым словом Scala.

Хотя у меня нет этой книги, классы Scala допускают использование псевдонимов для самих себя; self обычно выбирается. Вот почему вы можете захотеть это сделать (не считая того, что вы можете ограничить тип, которым может быть класс, когда вы указываете псевдоним):

class A {
  self =>
  val a = 7
  class B {
    val a = 7             // Uh-oh, we've shadowed the parent class a.
    val outerA = self.a   // Whew, we haven't lost it!
  }
}

Таким образом, self почти наверняка является классом, реализующим метод getPageSizeConcurrently.

Не видя больше кода, я не понимаю, почему именно он написан именно так (мне это кажется странным). Но здесь нет никакого странного сообщения методу.

(Между прочим, обратите внимание, что формально возможно определить актор, который расширяет трейт Function. Таким образом, вы могли бы фактически отправить сообщение функции (объекту функции, а не методу). Но синтаксис будет выглядеть не так, как у тебя выше)

person Rex Kerr    schedule 19.07.2011
comment
Спасибо, что указали мне правильное направление! Вы были правы, предположив, что я думал о self как о ключевом слове Scala. Я обновил свой вопрос, чтобы включить эту новую информацию. - person Chris Frederick; 19.07.2011

Хотя акторы не привязаны к потокам, как это было в более ранних версиях Scala, self сравнимо с Thread.current. Вы используете его, потому что Thread.current не имеет необходимых методов для просмотра текущего потока как актора.

"Какой класс или объект имеет getPageSizeConcurrently в качестве одного из своих методов?" - Рекс Керр

"Насколько я могу судить, ничего..." — Крис

Я предполагаю, что self пытается рассматривать текущий поток как действующее лицо.

Примечание. Будьте осторожны при использовании self в REPL.

person agilesteel    schedule 19.07.2011