对Scala新手的一个隐含问题似乎是:编译器在哪里寻找隐含?我的意思是隐含的,因为这个问题似乎永远不会完全形成,好像没有它的话.:-)例如,integral下面的值来自哪里?
scala> import scala.math._
import scala.math._
scala> def foo[T](t: T)(implicit integral: Integral[T]) {println(integral)}
foo: [T](t: T)(implicit integral: scala.math.Integral[T])Unit
scala> foo(0)
scala.math.Numeric$IntIsIntegral$@3dbea611
scala> foo(0L)
scala.math.Numeric$LongIsIntegral$@48c610af
Run Code Online (Sandbox Code Playgroud)
对于那些决定学习第一个问题的答案的人来说,另一个问题是,在某些明显模糊的情况下(但无论如何编译),编译器如何选择使用哪个隐式?
例如,scala.Predef定义两个转换String:一个转换为WrappedString另一个转换为StringOps.然而,这两个类都有很多方法,所以为什么Scala不会在调用时抱怨歧义map?
注意:这个问题的灵感来自另一个问题,希望以更一般的方式陈述问题.该示例是从那里复制的,因为它在答案中被引用.
我见过一个implicitly在Scala示例中使用的函数.它是什么,它是如何使用的?
scala> sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo {
| implicit def stringImpl = new Foo[String] {
| def apply(list : List[String]) = println("String")
| }
| implicit def intImpl = new Foo[Int] {
| def apply(list : List[Int]) = println("Int")
| }
| } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
defined trait Foo
defined module Foo
foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit
scala> foo(1)
<console>:8: error: …Run Code Online (Sandbox Code Playgroud) pimp-my-library模式允许我通过提供从该类到实现该方法的类的隐式转换,似乎向类添加方法.
斯卡拉不允许两个这样的隐式转换正在发生,但是,我不能得到A到C使用隐含A于B和另一个隐含的B对C.有没有办法解决这个限制?
假设我有一个类型类,证明Shapeless副产品中的所有类型都是单例类型:
import shapeless._
trait AllSingletons[A, C <: Coproduct] {
def values: List[A]
}
object AllSingletons {
implicit def cnilSingletons[A]: AllSingletons[A, CNil] =
new AllSingletons[A, CNil] {
def values = Nil
}
implicit def coproductSingletons[A, H <: A, T <: Coproduct](implicit
tsc: AllSingletons[A, T],
witness: Witness.Aux[H]
): AllSingletons[A, H :+: T] =
new AllSingletons[A, H :+: T] {
def values = witness.value :: tsc.values
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以证明它适用于简单的ADT:
sealed trait Foo
case object Bar extends Foo
case object Baz extends Foo
Run Code Online (Sandbox Code Playgroud)
然后: …
在尝试找到另一个问题([1])的解决方案时,我遇到了一个不同的隐式扩展错误.我正在寻找关于这意味着什么的解释
这是用例:
scala> implicit def ordering[T](implicit conv: T => Ordered[T], res: Ordering[Ordered[T]]) = Ordering.by(conv)
ordering: [T](implicit conv: (T) => Ordered[T],implicit res: Ordering[Ordered[T]])scala.math.Ordering[T]
scala> def foo[T <% Ordered[T]](s : Seq[T]) = s.sorted
<console>:6: error: diverging implicit expansion for type Ordering[T]
starting with method ordering in object $iw
def foo[T <% Ordered[T]](s : Seq[T]) = s.sorted
^
Run Code Online (Sandbox Code Playgroud) 这应该是一个微不足道的问题,但我无法在stackoverflow上明确找到它.
如果用户不提供,将隐式定义以下内容.
但是我已经读过某个地方(我现在似乎无法找到),有些情况下编译器不会隐式实现它们.
这些条件是什么?
以下是Hands-on Scala.js电子书中的一个示例:
package webpage
import org.scalajs.dom.ext.Ajax
import scala.scalajs.js
import scala.scalajs.js.annotation.JSExport
import scalatags.JsDom.all._
import org.scalajs.dom
import dom.html
@JSExport
object HelloWorld1 extends {
@JSExport
def main(target: html.Div) = {
lazy val box = input(
`type`:="text",
placeholder:="Type here!"
).render
lazy val output = div(
height:="400px",
overflowY:="scroll"
).render
box.onkeyup = (e: dom.Event) => {
output.innerHTML = "Loading..."
fetchWeather(box.value)
}
target.appendChild(
div(
h1("Weather Search"),
p(
"Enter the name of a city to pull the ",
"latest weather data from api.openweathermap.com!"
),
p(box),
hr, output, hr …Run Code Online (Sandbox Code Playgroud) Scala implicits非常强大.我很好奇它们是Scala的一个新的/独特的功能,还是已经存在于其他编程语言中的概念.
谢谢.
编辑:
为了澄清我的问题,是的,我正在谈论这个具体的实施.一开始有"隐含的东西"似乎很奇怪,但是已经使用它一段时间并看到别人如何使用它,我对它的工作效果印象深刻.
请原谅这个问题的长度.
我经常需要在我的代码的一层创建一些上下文信息,并在其他地方使用该信息.我通常发现自己使用隐式参数:
def foo(params)(implicit cx: MyContextType) = ...
implicit val context = makeContext()
foo(params)
Run Code Online (Sandbox Code Playgroud)
这是有效的,但是需要隐式参数传递很多,在介入函数的布局之后污染图层的方法签名,即使他们自己并不关心它.
def foo(params)(implicit cx: MyContextType) = ... bar() ...
def bar(params)(implicit cx: MyContextType) = ... qux() ...
def qux(params)(implicit cx: MyContextType) = ... ged() ...
def ged(params)(implicit cx: MyContextType) = ... mog() ...
def mog(params)(implicit cx: MyContextType) = cx.doStuff(params)
implicit val context = makeContext()
foo(params)
Run Code Online (Sandbox Code Playgroud)
我发现这种方法很难看,但它确实有一个优点:它的类型安全.我肯定知道mog会收到正确类型的上下文对象,或者它不会编译.
如果我可以使用某种形式的"依赖注入"来定位相关的上下文,它将减轻混乱.引号表明这与Scala中常见的依赖注入模式不同.
起点foo和终点mog可以存在于系统的非常不同的级别.例如,foo可能是用户登录控制器,mog可能正在进行SQL访问.可能有许多用户同时登录,但只有一个SQL层实例.每次mog由不同的用户调用时,需要不同的上下文.因此,上下文不能被烘焙到接收对象中,也不想以任何方式合并这两个层(如Cake Pattern).我还宁愿不依赖像Guice或Spring这样的DI/IoC库.我发现它们很重,不太适合Scala.
所以我认为我需要的东西是mog让它在运行时为它检索正确的上下文对象,有点像在ThreadLocal其中有一个堆栈: …