Scala收藏中的森林砍伐

Scala收藏中的森林砍伐,scala,collections,implicits,Scala,Collections,Implicits,从Scala系列的设计中,我了解到: scala> BitSet(1,2,3) map (_ + "a") res7: scala.collection.immutable.Set[String] = Set(1a, 2a, 3a) 不构建中间数据结构:新的数据集是在使用构建器迭代位集时构建的。事实上,在这种情况下,这是显而易见的,因为字符串的位集没有意义 列表中的地图呢?我非常确定以下内容构成了一个中间列表: scala> List(1,2,3) map (_ -> "fo

从Scala系列的设计中,我了解到:

scala> BitSet(1,2,3) map (_ + "a")
res7: scala.collection.immutable.Set[String] = Set(1a, 2a, 3a)
不构建中间数据结构:新的数据集是在使用构建器迭代位集时构建的。事实上,在这种情况下,这是显而易见的,因为字符串的位集没有意义

列表中的地图呢?我非常确定以下内容构成了一个中间列表:

scala> List(1,2,3) map (_ -> "foo") toMap
res8: scala.collection.immutable.Map[Int,java.lang.String] =
    Map(1 -> foo, 2 -> foo, 3 -> foo)
即列表
列表((1,foo),(2,foo),(3,foo))
。如果没有,怎么办?那么,下面呢

scala> Map.empty ++ (List(1,2,3) map (_ -> "foo"))
res10: scala.collection.immutable.Map[Int,java.lang.String] =
    Map(1 -> foo, 2 -> foo, 3 -> foo)
这一次,从我从
++
类型中似乎了解到:

def ++ [B >: (A, B), That]
       (that: TraversableOnce[B])
       (implicit bf: CanBuildFrom[Map[A, B], B, That]): That
我认为这可能是因为地图是动态构建的,而没有构建中间列表

是这样吗?如果是,这是确保森林砍伐的标准方法还是有更直接的语法?

示例1)正确,没有中间列表

2) 是的,你有一份即时列表

3) 同样是的,从括号中的内容可以得到一个相互编辑的列表。没有“魔法”在起作用。如果括号中有某些内容,则首先对其求值

我不确定你在这里所说的“森林砍伐”是什么意思:根据维基百科,这意味着消除树木结构。如果您的意思是删除中间列表,那么应该使用视图。请参见此处的示例:

因此,如果没有中间结果,您的示例将是

BitSet(1,2,3).view.map(_ + "a").toSet
toSet
是必需的,因为否则您会有一个
IterableView[String,Iterable[\u]]]

还有一个执行转换操作的
force
方法,但这似乎有一个坏习惯,就是返回一个更通用的类型(也许有人可以给出一个理由):


您可以使用
breakOut
确保不创建中间集合。例如:

// creates intermediate list.
scala> List((3, 4), (9, 11)).map(_.swap).toMap 
res542: scala.collection.immutable.Map[Int,Int] = Map(4 -> 3, 11 -> 9)

scala> import collection.breakOut
import collection.breakOut

// doesn't create an intermediate list.
scala> List((3, 4), (9, 11)).map(_.swap)(breakOut) : Map[Int, Int]
res543: Map[Int,Int] = Map(4 -> 3, 11 -> 9)
你可以阅读更多关于它的内容

更新:

如果阅读
breakOut
的定义,您会注意到它基本上是一种创建预期类型的
CanBuildFrom
对象并将其显式传递给方法的方法
breakOut
只需输入以下样板文件即可

// Observe the error message. This will tell you the type of argument expected.
scala> List((3, 4), (9, 11)).map(_.swap)('dummy)
<console>:16: error: type mismatch;
 found   : Symbol
 required: scala.collection.generic.CanBuildFrom[List[(Int, Int)],(Int, Int),?]
              List((3, 4), (9, 11)).map(_.swap)('dummy)
                                                ^

// Let's try passing the implicit with required type.
// (implicitly[T] simply picks up an implicit object of type T from scope.)
scala> List((3, 4), (9, 11)).map(_.swap)(implicitly[CanBuildFrom[List[(Int, Int)], (Int, Int), Map[Int, Int]]])
// Oops! It seems the implicit with required type doesn't exist.
<console>:16: error: Cannot construct a collection of type Map[Int,Int] with elements of type (Int, Int) based on a coll
ection of type List[(Int, Int)].
              List((3, 4), (9, 11)).map(_.swap)(implicitly[CanBuildFrom[List[(Int, Int)], (Int, Int), Map[Int, Int]]])

// Let's create an object of the required type ...
scala> object Bob extends CanBuildFrom[List[(Int, Int)], (Int, Int), Map[Int, Int]] {
     |   def apply(from: List[(Int, Int)]) = foo.apply
     |   def apply() = foo.apply
     |   private def foo = implicitly[CanBuildFrom[Nothing, (Int, Int), Map[Int, Int]]]
     | }
defined module Bob

// ... and pass it explicitly.
scala> List((3, 4), (9, 11)).map(_.swap)(Bob)
res12: Map[Int,Int] = Map(4 -> 3, 11 -> 9)

// Or let's just have breakOut do all the hard work for us.
scala> List((3, 4), (9, 11)).map(_.swap)(breakOut) : Map[Int, Int]
res13: Map[Int,Int] = Map(4 -> 3, 11 -> 9)
//观察错误消息。这将告诉您所需的参数类型。
scala>List((3,4),(9,11)).map(u.swap)('dummy)
:16:错误:类型不匹配;
发现:符号
必需:scala.collection.generic.CanBuildFrom[List[(Int,Int)],(Int,Int),?]
列表((3,4),(9,11)).map(u.swap)('dummy)
^
//让我们尝试用必需的类型传递隐式。
//(隐式[T]只是从作用域中拾取类型为T的隐式对象。)
scala>List((3,4),(9,11)).map(u.swap)(隐式地[CanBuildFrom[List[(Int,Int)],(Int,Int),map[Int,Int]]
//哎呀!似乎不存在具有必需类型的隐式。
:16:错误:无法使用基于coll的类型(Int,Int)的元素构造类型映射[Int,Int]的集合
类型列表的节[(Int,Int)]。
List((3,4)、(9,11)).map(u.swap)(隐式地[CanBuildFrom[List[(Int,Int)],(Int,Int),map[Int,Int]]
//让我们创建一个所需类型的对象。。。
scala>对象Bob扩展了CanBuildFrom[List[(Int,Int)],(Int,Int),Map[Int,Int]]{
|def apply(from:List[(Int,Int)])=foo.apply
|def apply()=foo.apply
|private def foo=隐式[CanBuildFrom[Nothing,(Int,Int),Map[Int,Int]]
| }
定义模块Bob
// ... 并明确地传递它。
scala>List((3,4)、(9,11)).map(u.swap)(Bob)
res12:Map[Int,Int]=Map(4->3,11->9)
//或者让我们让breakOut为我们做所有的艰苦工作。
scala>List((3,4)、(9,11)).map(u.swap)(breakOut):map[Int,Int]
res13:Map[Int,Int]=Map(4->3,11->9)

毁林意味着消除中间树结构。列表只是一个退化树,其中每个节点的左子节点为元素叶,右子节点为另一个节点,因此该术语也可以应用于列表。谢谢。大约3)我没想到会有奇迹发生,但我希望键入上下文会引导++为作业选择正确的隐式(就像read在haskell中选择正确的typeclass实例一样)。谢谢,这正是我想要的。我不确定的是,scala为什么抱怨
List((3,4)、(9,11)).map(u.swap):map[Int,Int]
,而不是使用我显式设置的类型约束来选择正确的隐式(就像read根据上下文在haskell中选择正确的typeclass实例一样)。是因为隐式的不那样工作(我完全理解,我知道子类型会让一切变得困难),还是我在这种特殊情况下忽略了什么?@DuncanMcGregor:我从过去5天以来就没有关闭过REPL。我在日常发展中大量使用它。:-)@邓肯·麦克格雷戈:我的窗口终于崩溃了-D@missingfaktor我肯定是我的错@DuncanMcGregor:LOL.很好。:-)
// creates intermediate list.
scala> List((3, 4), (9, 11)).map(_.swap).toMap 
res542: scala.collection.immutable.Map[Int,Int] = Map(4 -> 3, 11 -> 9)

scala> import collection.breakOut
import collection.breakOut

// doesn't create an intermediate list.
scala> List((3, 4), (9, 11)).map(_.swap)(breakOut) : Map[Int, Int]
res543: Map[Int,Int] = Map(4 -> 3, 11 -> 9)
// Observe the error message. This will tell you the type of argument expected.
scala> List((3, 4), (9, 11)).map(_.swap)('dummy)
<console>:16: error: type mismatch;
 found   : Symbol
 required: scala.collection.generic.CanBuildFrom[List[(Int, Int)],(Int, Int),?]
              List((3, 4), (9, 11)).map(_.swap)('dummy)
                                                ^

// Let's try passing the implicit with required type.
// (implicitly[T] simply picks up an implicit object of type T from scope.)
scala> List((3, 4), (9, 11)).map(_.swap)(implicitly[CanBuildFrom[List[(Int, Int)], (Int, Int), Map[Int, Int]]])
// Oops! It seems the implicit with required type doesn't exist.
<console>:16: error: Cannot construct a collection of type Map[Int,Int] with elements of type (Int, Int) based on a coll
ection of type List[(Int, Int)].
              List((3, 4), (9, 11)).map(_.swap)(implicitly[CanBuildFrom[List[(Int, Int)], (Int, Int), Map[Int, Int]]])

// Let's create an object of the required type ...
scala> object Bob extends CanBuildFrom[List[(Int, Int)], (Int, Int), Map[Int, Int]] {
     |   def apply(from: List[(Int, Int)]) = foo.apply
     |   def apply() = foo.apply
     |   private def foo = implicitly[CanBuildFrom[Nothing, (Int, Int), Map[Int, Int]]]
     | }
defined module Bob

// ... and pass it explicitly.
scala> List((3, 4), (9, 11)).map(_.swap)(Bob)
res12: Map[Int,Int] = Map(4 -> 3, 11 -> 9)

// Or let's just have breakOut do all the hard work for us.
scala> List((3, 4), (9, 11)).map(_.swap)(breakOut) : Map[Int, Int]
res13: Map[Int,Int] = Map(4 -> 3, 11 -> 9)