2012-07-15 105 views
7

现在我看到有一个相关的问题问的这些运营商(<:<,<%<,=:=)在这里做的:<:<,<%<,=:=的Scala实现究竟如何在编译器中工作?

What do <:<, <%<, and =:= mean in Scala 2.8, and where are they documented?

但我仍然感到困惑的具体实现。特别是,我假设一旦你放置了一个隐含的参数来断言一个特定的关系,那么你可以使用变量,就好像它们已经被自动正确地转换一样。这将编译:

class Foo[T](a: T) { 
    def splitit(implicit ev: T <:< String) = a split " " 
} 

但是,如何在编译器中实际工作?是否有一些神奇的编译器支持这些运算符,如果没有,那么允许它从定义中推断这种关系的底层机制是什么? (这个机制是专门为了让这些操作符工作而添加的,它们对这些特定的操作符有多特殊?)似乎有点神奇,你可以放置一个额外的隐式参数,它以某种方式改变了编译器对类型的解释。

+2

他们的来源https://github.com/scala/scala/blob/v2.9.2/src/library/scala/Predef.scala#L394 – pedrofurla 2012-07-15 04:12:17

回答

8

该实现有点棘手,但没有什么神奇。

有一个在Predef一个隐含的方法当你尝试调用你的方法可以用于任何A

implicit def conforms[A]: A <:< A 

提供A <:< A类型的值,它会寻找T <:< String类型的隐含价值。编译器将检查conforms[T]是否为有效值。假设TNothing,那么将会有一个隐含的值Nothing <:< Nothing,它将允许您的方法调用进行编译。由于道路<:<定义

sealed abstract class <:<[-From, +To] 

From容许变化并To容许变化了。因此Nothing <:< Nothing仍然是有效的Nothing <:< String,因为NothingString的子类型。 A String <:< String也是有效的Nothing <:< String,因为String是超类型Nothing(但编译器似乎总是选择第一种类型)。

你可以调用它的String方法,因为<:<也延伸=>又名Function1并作为从TString的隐式转换,基本上结束了做一个安全的演员。

=:=是相同的东西,除了它没有任何差异注释定义,所以类型必须完全匹配。

<%<被定义像<:<但隐式方法是有点不同的,它增加了另一参数来指定绑定

implicit def conformsOrViewsAs[A <% B, B]: A <%< B 

它还弃用的图。

+0

谢谢!以下是解释编译器如何让你调用字符串方法(或其他)的关键: _你可以调用字符串方法,因为<:<也扩展=>又名Function1,用作从T到字符串的隐式转换,基本上结束了做一个安全cast._ – 2012-07-22 00:17:33