Подтвердить что ты не робот

Понимание блоков Scala

Мне трудно найти конкретные ответы на то, что я знаю, что-то тривиальное. Я хотел бы понять, как блоки работают в Scala. Я исхожу из java/ruby ​​background, и кажется, что scala имеет совершенно другой способ использования блоков.

Следующий код из Play! Веб-сайт платформы. Я хотел бы понять, что Действие семантически. Это объект или функция, которая принимает блок, или, возможно, ни один.

object Application extends Controller {

  def index = Action {
    Ok(views.html.index("Your new application is ready."))
  }

}

Если это функция, возможно, это синтаксический сахар для следующего (в этом случае, как scala проходит вокруг блоков за кадром):

  def index = Action({
    Ok(views.html.index("Your new application is ready."))
  })

Или это какой-то синтаксис scala, о котором я не знаю.

Любые ссылки на исходный код scala помогут мне понять, как это работает за кулисами.

4b9b3361

Ответ 1

Вам лучше подумать о scala блоках как java-анонимных классах (например, как функции Guava), а не как ruby-блоки. На самом деле, если вы декомпилируете код scala, вы увидите более или менее тот же код (взятый из примеров Guava):

Function<String, Integer> lengthFunction = new Function<String, Integer>() {
  public Integer apply(String string) {
    return string.length();
  }
};

Разница заключается в том, что scala предоставляет много синтаксического сахара и позволяет вам писать код выше:

val lengthFunction = { string: String => string.length }

Что касается конкретного примера действия:

def index = Action({
    Ok(views.html.index("Your new application is ready."))
  })

Здесь, скорее всего, объект с методом apply. Другой scala sugar: language позволяет писать Foo(bar) и означает Foo.apply(bar). Затем вы можете опустить круглые фигурные скобки, когда ваш вызов не является двусмысленным, так что да, это фактически метод, получивший название:

def index = Action({
    Ok(views.html.index("Your new application is ready."))
})

И что-то вроде этого в качестве подписи:

object Action {
  def apply(block: => Result) = ???
}

Как уже было сказано @yan, это способ scala сказать эй, я - функция, которая принимает другую функцию, которая производит результат

Вызов Desugared будет выглядеть как

def index = Action.apply(new AbstractFunction[Result] {
        def apply() = Ok.apply(views.html.index.apply("..."))
})

Ответ 2

Здесь есть несколько вещей. Action - это объект, который реализует метод apply(), что вызывается, когда вы рассматриваете объект как функцию. Существует несколько версий apply() . Первая реализация использует параметр by-name.

Scala поддерживает концепцию, известную как "параметры имени", которые аналогичны нормальным параметрам, за исключением того, что они оцениваются только тогда, когда выполняется код, который ссылается на них. Они помогают создавать конструкты, которые выглядят так, как будто они являются частью языка, не прибегая к макросам. В этом случае блок, окружающий Ok(..), является просто регулярным блоком операторов, причем последнее значение используется как значение блока. Пример, который вы предоставили, будет работать без брекетов. Вы просто передаете результат метода Ok apply методу Action apply.

Вторая версия apply() действительно принимает полную анонимную функцию, которая отображает запрос на результат. В этом случае вы можете передать анонимную (или названную) функцию.