2016-10-09 4 views
3

Я не определил функцию ev в любом месте. Затем, как работает нижний код? Не следует ли определять какие-либо признаки в какой-либо области их использования?Передача и использование неявной функции без ее определения

def same[T, U](x: U)(implicit ev: U => T): T = {ev(x)} 
same(2) // 2 
+2

Чтобы расширить ответ @TravisBrown, вы также можете выполнить: 'same [Long, Int] (2)' и увидеть, что он все еще компилируется, потому что 'Int' имеет неявное имя' int2long', определенное на нем, что эта работа. Когда такая магия случается, всегда думайте о том, какие импликации попадают в сферу действия для вас, без явного запроса их –

+0

. Спасибо Yuval, запутанная часть была на каком основании компилятор вывел 'T' (до того, как он искал неявный). Это моя первая кисть с неявным методом $ соответствия. – Samar

ответ

5

Каждый раз, когда у вас есть вопросы, как это, хорошее место, чтобы начать это с помощью Reflection API Scala в REPL, чтобы попросить компилятор, что происходит:

scala> import scala.reflect.runtime.universe.{ reify, showCode } 
import scala.reflect.runtime.universe.{reify, showCode} 

scala> def same[T, U](x: U)(implicit ev: U => T): T = ev(x) 
same: [T, U](x: U)(implicit ev: U => T)T 

scala> showCode(reify(same(2)).tree) 
res0: String = $read.same(2)(Predef.$conforms) 

Так ev предоставленный Predef.$conforms, неявный метод, который даст вам экземпляр A <:< A для любого A, где <:< распространяется Function1.

Так что это одна подсказка. Выяснение остальных требует немного подумать о типе вывода. Когда вы звоните same(2), компилятор выясняет, что выражение 2 имеет тип Int и сообщает, что U - Int. Затем нужно выяснить, что такое T, и для этого он ищет неявные функции от Int до x для некоторого типа x.

Это где $conforms приходит. Это единственный такой метод в области видимости, поэтому компилятор выбирает его, что означает, что ev имеет тип Int => Int и T должен быть Int, и вы сделали.

+0

Это аккуратный трюк. Я всегда использую 'scalac -Xprint..', чтобы посмотреть на дерево. –

+0

@YuvalItzchakov Да, 'scalac -Xprint' тоже полезен, но я считаю его более шумным и менее удобным для автономных примеров, подобных этому. –

+0

Это определенно приносит гораздо больше шума. Я обязательно запомню это :) –

Смежные вопросы