Какие концепции Scala используются для обеспечения работы Scalatra DSL?

Я пытаюсь попасть в Scala, пытаясь использовать Scalatra. Я закончил курс Мартина Одерски на Coursera некоторое время назад, но мне до сих пор трудно понять, как это работает:

package com.example.app
import org.scalatra._

class HelloWorldApp extends ScalatraFilter {
  get("/") {
    <h1>Hello, {params("name")}</h1>
  }
}

Этот пример взят с главной страницы Scalatra: http://www.scalatra.org/

Как выполняется это заявление:

get("/") {
    Hello, {params("name")}
}

Является ли {} параметром метода get()? Можете ли вы объяснить, какие возможности языка Scala здесь используются? Указатели на исходный код Scalatra были бы идеальным определением, что это было бы идеально.


person atok    schedule 11.07.2014    source источник
comment
В настоящее время я ожидаю, что это будет закрыто как неясное, что вы спрашиваете, или слишком широкое. Вероятно, вы понимаете некоторые утверждения. Можете ли вы более подробно указать, с какими частями у вас возникли проблемы?   -  person The Archetypal Paul    schedule 11.07.2014
comment
Отредактировал вопрос, чтобы сделать его менее широким :)   -  person atok    schedule 11.07.2014


Ответы (2)


get определяется в CoreDsl< /а> следующим образом

def get(transformers: RouteTransformer*)(block: => Any): Route

Итак, get принимает два параметра: последовательность преобразователей маршрутов (строки неявно преобразуются в преобразователи маршрутов) и метод без параметров, который выводит что-то типа Any. Интересной частью здесь является второй параметр.

Первое, что нужно понять, это то, что методы без параметров в качестве аргументов функций в Scala обрабатываются особым образом, а именно как вызов по имени, см. Автоматическое построение замыканий в зависимости от типа, а также Справочник по языку Scala, раздел 6.6, с. 78, то есть с. 86 PDF-файла:

Случай формального параметра с типом метода без параметров => T рассматривается отдельно. В этом случае соответствующее выражение фактического аргумента e не оценивается перед приложением. Вместо этого каждое использование формального параметра в правой части правила перезаписи влечет за собой переоценку e. Другими словами, порядок оценки для =>-параметров — вызов по имени, тогда как порядок оценки для обычных параметров — вызов по значению.

Второй аспект заключается в том, что в приложении функции аргументы могут быть заключены либо в () ("обычные" аргументы), либо в {} (точнее, в этом случае они должны быть блочные выражения, и они могут даже начинаться с новой строки), см. Справочник по языку Scala по применению функций, раздел 6.6 на с. 77, то есть с. 85 PDF-файла.

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

Части следующего вопроса также могут быть интересны Какая разница между несколькими списками параметров и несколькими параметрами в списке в Scala?

person godfatherofpolka    schedule 11.07.2014
comment
Спасибо! Это показывает необходимый уровень знаний для сознательного использования таких инструментов, как Scalatra. - person atok; 11.07.2014
comment
Хорошо, может быть. На самом деле, вы можете использовать его, не зная большей части этого - как говорит @godfatherofpolka, это то, что делает его привлекательным с точки зрения DSL/ключевых слов, но пользователю не нужно знать, как они реализованы. - person The Archetypal Paul; 11.07.2014
comment
Не могли бы вы объяснить, как анализируется и оценивается строка ‹h1›...? Существуют ли для этого заранее определенные литералы? Не могу найти ничего связанного в исходном коде. - person DimG; 07.03.2019
comment
@DimG Scala имеет (несколько спорные) литералы XML: scala-lang.org/files/archive/spec/2.12/ Строка ‹h1›... является их примером. - person godfatherofpolka; 07.03.2019

Является ли {} параметром метода get()?

да. get будет иметь два списка параметров. Один для пути "\", а другой для выполнения блока. Блоки заключены в {}, параметры в (). Таким образом, вам, похоже, придется называть это как

class HelloWorldApp extends ScalatraFilter {
  get("/") ({
    <h1>Hello, {params("name")}</h1>
  })
}

но есть некоторый синтаксический сахар, который позволяет передавать один параметр в {} без добавления (). Вы чаще видите это в таких вещах, как

myList foreach { do_something() }

Это очень полезная функция для написания того, что выглядит и используется как новые управляющие структуры, но на самом деле является просто функциями.

person The Archetypal Paul    schedule 11.07.2014