2013-11-24 2 views
0

Я пытаюсь понять подключения к базе данных в Scala, используя стандартную библиотеку Anorm в игровой инфраструктуре. Игра имеет образец пример «Компьютерная база данных», где одна из функций пытается извлечь компьютер из БД:Понимание вызова по имени с currying в Scala

DB.withConnection { implicit connection => 
    SQL("select * from computer where id = {id}").on('id -> id).as(Computer.simple.singleOpt) 
} 

Если посмотреть на функции подписи withConnection это так:

def withConnection [A] (block: (Connection) ⇒ A)(implicit app: Application): A 
Execute a block of code, providing a JDBC connection. The connection and all created statements are automatically released. 
**block** Code block to execute. 

Мой вопрос заключается в том, как сопоставить каждое значение вызова функции с определением функции? Например, что такое A (это весь запрос SQL, но что означает тип возврата?). Что такое неявное приложение в этом случае? Где это определено?

ответ

3

правды этот пример сбивает с толком, так как он сочетает в себе несколько функций языка

  1. параметры типа (дженерик)
  2. Карринга (= два списка аргументов)
  3. анонимного инлайн функции (функциональный блок)
  4. неявные аргументы (которые взяты из контекста)

Как всегда, когда вопросы искусство становится сложным, позволяет «разобраться» один за другим

(1) A - это параметр типа. Это заменяется подходящим типом при каждом вызове функции. Так как A упоминается в двух местах списка аргументов и в типе возвращаемого значения, это означает, что любой тип, который вы используете, тип результата переданного функционального блока будет таким же, как и общий тип возврата. Вы можете явно определить A при использовании функции, но обычно вы можете ее оставить, так как компилятор может определить используемый тип.

(2) каррирование легко понять. Эта функция здесь имеет только два списка параметров. Это означает, что вы можете применить эту функцию в несколько этапов. Сначала нанесите список левый параметр:

def myBlock(connection:Connection):SQL = 
     SQL("select ......" ..... 

val pf = DB.withConnection(myBlock) 

Вопрос: Какой объект является pf? что такое тип иса? Ответ: это функция, принимающая один аргумент, объект приложения

Таким образом, тип pf будет Application => SQL, поскольку в первом, частичном приложении функции мы просто передали в другую функцию с типом возвращаемого SQL, таким образом параметр типа A выводится как SQL

(3), но в приведенном выше коде, мы определили функцию myBlock обычным способом, и мы дали это явно название «myBlock». Это необязательно. Мы можем определить одну и ту же функцию только в строке, используя синтаксис блока.

(4) и теперь запутанная, «магическая» часть, implicits. Это очень особенная особенность Scala, где компилятор позволяет вам опустить некоторые значения или аргументы (в нашем случае). Вы не можете пропустить произвольные аргументы, но только аргументы, помеченные как implicit.Когда вы это сделаете, компилятор не сразу генерирует ошибку; скорее это выглядит в текущей области, если он может найти подходящий другой объект с тем же именем.

Фактически это означает, что в вашем примере должно быть какое-то значение «соединение» типа Connection, и должно быть значение «приложение» типа Application. Оба значения должны быть как-то видимыми в текущей области - то есть либо в качестве параметра, либо как значение в охватывающей области, либо как значение в сопутствующем объекте, либо вы могли бы явно ввести их в область с инструкцией import. Цель этой языковой функции - просто сохранить ваши типичные аргументы (приложение и подключение 9 снова и снова

+0

Я понимаю, что вы говорите один вопрос: этот SQL-запрос определен в 'package models', который импортируется в 'object Application', так как это делает объект' Application' видимым для неявного определения 'implicit app: Application' – Richeek

+0

не может дать вам точный ответ, мне придется посмотреть на код. извините. Просто догадка : может быть, он унаследован? Или, может быть, он был импортирован expliticly в охватывающую область или родительский класс? – Ichthyo

+0

Я проверю, что завтра ... еще один пример, который вы предоставили 'def myBlock (connection: Connection): SQL = ... 'не работает как таковой.Я должен импортировать' java.sql.Connection', чтобы найти класс 'Connection'. Однако' неявное соединение => ... 'работает без импорта. Это смущает! – Richeek