Scala 2.8和Scala 2.7最大的区别是什么?

我在Scala 2.7.5中写了一个相当大的程序,现在我期待2.8版本。 但是我很好奇Scala的这个巨大的飞跃将会如何影响我。

这两个版本的Scala最大的区别是什么? 也许最重要的是:

  • 需要重写什么吗?
  • 重写任何东西只是为了利用一些很酷的新function吗?
  • Scala 2.8的新特性究竟是什么?

您可以在这里findScala2.8 (2009年4月) 的新function预览,最近完成了这篇文章 (2009年6月)

  • 命名和默认参数
  • 嵌套注释
  • 包对象
  • @专门
  • 改进的集合(这里可能需要重写)
  • REPL将有命令完成(更多在这篇文章和其他技巧 )
  • 新的控制抽象(继续或中断)
  • 增强(Swing包装,表演,…)

“重写代码”不是一个义务(除了使用一些改进的集合),但是一些特性如继续 ( 维基百科 :控制状态的抽象表示,或者“剩余的计算”或“要执行的代码的其余部分“)可以给你一些新的想法。 在这里可以find一个很好的介绍,由丹尼尔 (在这个post中也发布了更详细和具体的答案 )写的。

注意: Netbeans上的Scala似乎可以在每晚2.8版本( 2.7.x的官方页面 )

跨越式发展

当您迁移时,编译器可以为您提供一些安全网。

  1. -deprecation编译2.7.7的旧代码,并按照所有弃用警告中的build议进行操作。
  2. 更新您的代码以使用unnnested包。 这可以通过重复运行这个正则expression式searchreplace来机械地完成。

     s/^(package com.example.project.*)\.(\w+)/$1\npackage $2/g 
  3. 编译2.8.0编译器,使用偏执命令行选项-deprecation -Xmigration -Xcheckinit -Xstrict-warnings -Xwarninit

  4. 如果您收到错误,错误could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T] ,则需要在types参数上添加一个隐式参数(或等同于上下文绑定)。

    之前:

     scala> def listToArray[T](ls: List[T]): Array[T] = ls.toArray <console>:5: error: could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T] def listToArray[T](ls: List[T]): Array[T] = ls.toArray ^ 

    后:

     scala> def listToArray[T: Manifest](ls: List[T]): Array[T] = ls.toArray listToArray: [T](ls: List[T])(implicit evidence$1: Manifest[T])Array[T] scala> def listToArray[T](ls: List[T])(implicit m: Manifest[T]): Array[T] = ls.toArray listToArray: [T](ls: List[T])(implicit m: Manifest[T])Array[T] 

    任何调用listToArray方法,本身都将T作为types参数,也必须接受Manifest作为隐式参数。 有关详细信息,请参阅Arrays SID 。

  5. 太久之前,你会遇到这样的错误:

     scala> collection.Map(1 -> 2): Map[Int, Int] <console>:6: error: type mismatch; found : scala.collection.Map[Int,Int] required: Map[Int,Int] collection.Map(1 -> 2): Map[Int, Int] ^ 

    您需要了解Maptypes是Predef中用于collection.immutable.Map的别名。

      object Predef { type Map[A, B] = collection.immutable.Map[A, B] val Map = collection.immutable.Map } 

    有三种名为Maptypes – 一个只读接口: collection.Map ,一个不可变的实现: collection.immutable.Map ,以及一个可变的实现: collection.mutable.Map 。 此外,图书馆定义了一组并行的MapLike行为,但这实际上是一个实现细节。

获得好处

  1. 用命名参数和默认参数replace一些重载方法。
  2. 使用生成的案例类的copy方法。

      scala> case class Foo(a: Int, b: String) defined class Foo scala> Foo(1, "a").copy(b = "b") res1: Foo = Foo(1,b) 
  3. List的方法签名概括为SeqIterableTraversable 。 由于集合类是在一个干净的层次结构中,你可以接受一个更一般的types。
  4. 使用注释与Java库集成。 您现在可以指定嵌套的注释,并且对注释是针对字段还是方法进行细化控制 。 这有助于使用Spring或JPA与Scala代码。

还有许多其他新function可以在开始迁移时安全地忽略,例如@specialized和Continuations。

VonC的答案很难改善,所以我甚至不会去尝试。 我会介绍一些他没有提到的其他东西。

首先,一些弃用的东西会去。 如果您的代码中存在弃用警告,则很可能无法再编译。

接下来,斯卡拉的图书馆正在扩大。 大多数情况下,常见的小模式,例如将exception捕获到EitherOption ,或将AnyRef转换成null映射到None的Option。 这些东西大多可以忽略,但是我厌倦了在博客上发布一些东西,后来有人告诉我它已经在Scala 2.8上。 实际上,我并没有厌倦它,而是,而且很高兴地习惯了它。 我在这里不是在谈论collections,这一个重大的修订。

现在,如果有人把这种图书馆改进的实际例子作为答案,那是很好的。 我很乐意提出所有这样的答案。

REPL不仅仅是命令完成。 它获得了很多东西,包括检查对象的AST的能力,或者将断点插入到REPL代码中的能力。

此外,Scala的编译器正在被修改,以便能够对IDE进行快速部分编译,这意味着我们可以期望它们对Scala变得更加“认识” – 通过查询Scala编译器本身的代码。

一个巨大的变化可能会被很多人忽视,尽pipe这会减less图书馆作者和用户的问题。 现在,如果你写下以下内容:

 package com.mystuff.java.wrappers import java.net._ 

您不是导入Java的net库,而是com.mystuff.javanet库,如comcom.mystuffcom.mystuff.javacom.mystuff.java.wrappers都在范围内,并且可以在内部findjava com.mystuff 。 随着Scala 2.8,只有wrappers获得范围。 因为有时候,你希望其余的一些在Scope中,所以现在可以使用一个替代的package语法:

 package com.mystuff.factories package ligthbulbs 

相当于:

 package com.mystuff.factories { package lightbulbs { ... } } 

碰巧把factorieslightbulbs纳入了范围。

需要重写什么吗?

 def takesArray(arr: Array[AnyRef]) {…} def usesVarArgs(obs: AnyRef*) { takesArray(obs) } 

需要成为

 def usesVarArgs(obs: AnyRef*) { takesArray(obs.toArray) } 

我不得不去访问那个IRC频道,但后来意识到我应该从这里开始。

这里有一个Eric Willigers的清单,他从2.2开始就一直在使用Scala。 这些东西中的一些似乎过时了更近的用户。

*从外包显式导入*

假设我们有

 package a class B 

更改

 package ac class D extends B 

 package ac import aB class D extends B 

要么

 package a package c class D extends B 

*从外包装import时使用完全合格的包装名称*

假设我们有

 package ab object O { val x = 1 } 

更改

 package abc import bOx 

 package abc import abOx 

*在容器方法调用中明确指定types参数时,添加新的types参数*

更改

 list.map[Int](f) 

 list.map[Int, List[Int]](f) 

更改

 map.transform[Value](g) 

 map.transform[Value, Map[Key, Value]](g) 

*使用sorting创buildsorting的地图,而不是转换为sorting*

  [scalac] found : (String) => Ordered[String] [scalac] required: Ordering[String] [scalac] TreeMap[String, Any](map.toList: _*)(stringToCaseInsensitiveOrdered _) 

*导入replacescala.collection.jcl的隐式转换*

* Immutable Map .update变成.update *

***从新弃用的List方法迁移 –
* elements * remove * sort * List.flatten(someList) * List.fromString(someList, sep) * List.make

***使用列表方法* diff * iterator * filterNot * sortWith * someList.flatten * someList.split(sep) * List.fill

*使用scala.tools.nsc.Settings时的类path*

http://thread.gmane.org/gmane.comp.lang.scala/18245/focus=18247 settings.classpath.value = System.getProperty(“java.class.path”)

*避免错误:_必须遵循方法; 不能跟随(任何)=>布尔*

更换

 list.filter(that.f _) 

 list.filter(that f _) 

要么

 list.filter(that.f(_)) 

>>>

从不推荐使用的枚举方法iterator map *使用枚举方法values.iterator values.map

Iterator.fromValues(a, b, c, d) Iterator(a, b, c, d)

*避免不build议使用的typesCollection *改用Iterable

*更改初始化顺序*

假设我们有

 trait T { val v val w = v + v } 

更换

 class C extends T { val v = "v" } 

 class C extends { val v = "v" } with T 

*避免不必要的val for (val x <- ...) *

*避免尾随逗号*