对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?
注意:这个问题的灵感来自另一个问题,希望以更一般的方式陈述问题.该示例是从那里复制的,因为它在答案中被引用.
一个Scala中最强大的模式是充实,我的图书馆*模式,它采用隐式转换为出现添加方法,以现有的类,而不需要动态方法解析.例如,如果我们希望所有字符串都有spaces计算他们有多少个空格字符的方法,我们可以:
class SpaceCounter(s: String) {
def spaces = s.count(_.isWhitespace)
}
implicit def string_counts_spaces(s: String) = new SpaceCounter(s)
scala> "How many spaces do I have?".spaces
res1: Int = 5
Run Code Online (Sandbox Code Playgroud)
不幸的是,这种模式在处理泛型集合时遇到了麻烦.例如,已经询问了许多关于按顺序对项目进行分组的问题.没有内置的东西可以一次性工作,所以这似乎是使用泛型集合C和泛型元素类型的rich-my-library模式的理想候选者A:
class SequentiallyGroupingCollection[A, C[A] <: Seq[A]](ca: C[A]) {
def groupIdentical: C[C[A]] = {
if (ca.isEmpty) C.empty[C[A]]
else {
val first = ca.head
val (same,rest) = ca.span(_ == first)
same +: (new SequentiallyGroupingCollection(rest)).groupIdentical
}
}
}
Run Code Online (Sandbox Code Playgroud)
当然,除了它不起作用.REPL告诉我们:
<console>:12: error: not found: …Run Code Online (Sandbox Code Playgroud) 我已经阅读了关于scala.math.Integral的问题的答案但是我不明白当作为隐式参数传递时会发生什么.(我想我一般都理解隐式参数概念).Integral[T]
让我们考虑一下这个功能
import scala.math._
def foo[T](t: T)(implicit integral: Integral[T]) { println(integral) }
Run Code Online (Sandbox Code Playgroud)
现在我打电话给fooREPL:
scala> foo(0)
scala.math.Numeric$IntIsIntegral$@581ea2
scala> foo(0L)
scala.math.Numeric$LongIsIntegral$@17fe89Run Code Online (Sandbox Code Playgroud)
怎样的integral争论变得scala.math.Numeric$IntIsIntegral和scala.math.Numeric$LongIsIntegral?
我一直认为在scala中不可能进行多级隐式转换(除非你定义视图边界:http://docs.scala-lang.org/tutorials/FAQ/context-and-view-bounds.html)
但似乎类型系统存在缺陷或不一致.以下示例(改编自如何在Scala中链接implicits?)
class A(val n: Double){
def total = n + 10
}
object T1{
implicit def toA(n: Double): A = new A(n)
val i : Int = 5
println(i.total) //Why does this work?
println(5.2.total)
}
Run Code Online (Sandbox Code Playgroud)
我真的不明白为什么Int - > Double - > A的隐式转换有效.有人可以解释原因吗?谢谢
我是一名强大的Java开发人员,他最近开始尝试在我的空闲时间内学习Scala.我正在通过scala-lang.org中的示例 PDF来阅读Scala,并且很困惑第一个示例中的快速排序是如何工作的.这是代码:
object QuickSort extends App {
def sort(input: Array[Int]): Array[Int] = {
if(input.length <= 1) input
else
{
val pivot = input(input.length / 2)
Array.concat(
sort(input filter (pivot >)),
input filter (pivot ==),
sort(input filter (pivot <))
)
}
}
sort(Array(5, 4, 3, 2, 1)) foreach println
}
Run Code Online (Sandbox Code Playgroud)
我的问题不是语法或任何东西,但我对过滤函数的来源感到困惑.根据PDF,它说它来自Seq [T]类,并且所有数组都是Seq [T]的实例.这一切都很好,花花公子,在阅读PDF时,我很满意,也是一位非常开心的新手Scala开发人员.但后来我深入挖掘并开始查看Array [T]的scaladoc以及Array [T]的源代码,我不知道Array [T]类是如何扩展或继承Seq [T]特征的所有.我错过了什么?
在我的代码中的某个时刻,我想在A上调用C方法.这可能吗?我提出的一个修复是从A - > C转换,但这似乎有点多余.
注意:
谢谢 ...
据我所知,集合库中没有共享特征来定义map方法(很可能是因为有不同的签名map).
我有一个可观察的值(想想一个ui系统中的属性),它有一个change事件.可以使用map方法映射可观察值.
但是,当我们使用已经有map方法的类型时,我们应该能够使用内置方法map.
所以代替:
prop map { x =>
x map { actualX =>
//do something
}
}
Run Code Online (Sandbox Code Playgroud)
我想这样使用它:
prop map { actualX =>
//do something
}
Run Code Online (Sandbox Code Playgroud)
我有一个简化的测试用例.首先是我使用的不同部分:
// leaving out the observable part
trait ObservableValue[T] {
def value: T
}
trait LowerPriorityImplicits {
// default implementation that adds a regular map method
implicit class RichObservableValue1[A](o: ObservableValue[A]) {
def map[B](f: A => B): ObservableValue[B] = new ObservableValue[B] {
def value …Run Code Online (Sandbox Code Playgroud) 有这个帖子,讨论implicits的链接,但我认为它不包括我的情况,因为我有通用implicits.演示此问题的示例项目位于此处.要重现这两条线应该被注释掉.
所以我对具体类型有许多含义,例如
implicit val ObjectIdColumnType: ColumnType[ObjectId] = MappedColumnType.base[ObjectId, Array[Byte]](
{ obj => obj.toByteArray }, { arr => new ObjectId(arr) }
)
Run Code Online (Sandbox Code Playgroud)
我希望所有这些都能自动生成GetResult[T]隐式val.因此我写了以下功能
implicit def getResultForTypedTypes[T](implicit bct: ColumnType[T]): GetResult[T] =
GetResult[T](r => bct.getValue(r.rs, r.currentPos))
Run Code Online (Sandbox Code Playgroud)
我希望这个功能与原型如
def << [T](implicit f: GetResult[T]): T = f(this)
Run Code Online (Sandbox Code Playgroud)
能够接受 GetResult[ObjectId]
可悲的是我得到了错误
Error:(78, 20) could not find implicit value for parameter f: slick.jdbc.GetResult[org.bson.types.ObjectId]
val id = r.<<[ObjectId]
^
Run Code Online (Sandbox Code Playgroud)
我启用了log-implicits,发现看似无关的隐式隐藏在某种程度上
Information:(78, 20) getResultForTypedTypes is not a valid implicit value for …Run Code Online (Sandbox Code Playgroud) 可能重复:
如何在Scala中链接implicits?
Scala可以在一个表达式中应用多个隐式转换吗?
考虑这个简单的例子:
case class Wrapper(s: String)
case class WrapperWrapper(w: Wrapper)
implicit def string2Wrapper(s: String) = Wrapper(s)
implicit def wrapper2WrapperWrapper(w: Wrapper) = WrapperWrapper(w)
// implicit conversation --> w = string2Wrapper("w")
val w: Wrapper = "w"
// implicit conversation --> ww = wrapper2WrapperWrapper(w)
val ww: WrapperWrapper = w
// does NOT compile!
// ideally --> sad = wrapper2WrapperWrapper(string2Wrapper("ww"))
val sad: WrapperWrapper = "ww"
Run Code Online (Sandbox Code Playgroud)
有没有办法在最后一行中进行"双重"转换?
我可以通过定义另一个隐含的方式帮助事情:
implicit def string2WrapperWrapper(s:String) = wrapper2WrapperWrapper(s)
Run Code Online (Sandbox Code Playgroud)
但似乎不应该这样......
假设我有一个名为LongArrayWritable的类型,它是一个Longs数组的盒装表示.我有隐式定义,在这些类型之间转换:
implicit def boxLongArray(array: Array[Long]) : LongArrayWritable { /*elided*/}
implicit def unboxLongArray(array: LongArrayWritable) : Array[Long] { /*elided*/}
Run Code Online (Sandbox Code Playgroud)
现在,我也有一些暗示,它们以通用形式在java.lang.Iterable和scala.collection.List [X]之间进行转换:
implicit def iterator2list[X](it : java.lang.Iterable[X]) : List[X] { /* elided */ }
implicit def list2iterator[X](list : List[X]) : java.lang.Iterable[X] { /* elided */ }
Run Code Online (Sandbox Code Playgroud)
使用这些定义,scala编译器可以推断java.lang.Iterable [LongArrayWritable]和List [Array [Long]](相当于iterator2list(iterator).map(unboxLongArray(_)))之间的隐式转换,或者这超出了implicits的功能,因此需要它自己的(显式?)隐式定义?
谢谢,
蒂姆
我看到了一些示例,其中转换函数T => S作为隐式参数传递.Scala 调用此函数view甚至提供特殊的语法糖view bound- 对于这种情况.
但是我们已经进行了隐式转换!我可以views用隐式转换替换这些(即作为隐式参数传递的转换函数)吗??我可以views用隐含的转换来做什么?
设T1, T2, T3三种类型。我们还定义了该类的两个给定实例Conversion,以便编译器可以从T1toT2和从T2to进行转换T3。
下面的代码可以正常编译:
type T1
type T2
type T3
given Conversion[T1, T2] with
override def apply(x: T1): T2 = ???
given Conversion[T2, T3] with
override def apply(x: T2): T3 = ???
val t1: T1 = ???
val t2: T2 = t1
val t3: T3 = t2
Run Code Online (Sandbox Code Playgroud)
但是当我们尝试从T1到 时会发生什么T3?编译器不会让我们:
val t3: T3 = t1
^^
Found: (t1: T1)
Required: T3
Run Code Online (Sandbox Code Playgroud)
我的问题:编译器无法本机(参见解决方法)链转换是否有特定原因?
我的解决方法 …