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

时间:2009-08-07 09:22:16

标签: scala

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

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

  • 是否需要重写任何内容?
  • 想要重写任何东西只是为了利用一些很酷的新功能吗?
  • Scala 2.8的新功能究竟是什么?

5 个答案:

答案 0 :(得分:37)

采取飞跃

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

  1. 根据2.7.7编译旧代码 与-deprecation,并按照 所有弃用的建议 警告。
  2. 更新您要使用的代码 没有包装的。这可以做到 通过反复运行机械地 这个正则表达式搜索 取代

    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],则需要在类型参数上添加隐式参数(或等效地,上下文绑定)。

    在:

    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作为类型参数的方法,也必须接受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]
                 ^
    

    您需要了解类型Map是Predef中collection.immutable.Map的别名。

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

    有三种类型Map - 只读接口:collection.Map,不可变实现:collection.immutable.Map,以及可变实现:collection.mutable.Map。此外,库定义了一组并行的特征MapLike中的行为,但这实际上是一个实现细节。

  6. 获得收益

    1. 使用命名和默认参数替换某些方法重载。
    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。由于集合类处于干净的层次结构中,您是否可以接受更通用的类型。
    4. 使用Annotations与Java库集成。您现在可以指定嵌套注释,并且注释是否针对字段或方法具有fine-grained control。这有助于将Spring或JPA与Scala代码一起使用。
    5. 您可以在开始迁移时安全地忽略许多其他新功能,例如@specialized和Continuations。

答案 1 :(得分:33)

您可以在这里找到preview of new feature in Scala2.8(2009年4月),最近this article完成(2009年6月)

  • 命名和默认参数
  • 嵌套注释
  • 包对象
  • @specialized
  • 改进的集合(这里可能需要重写)
  • REPL将完成命令(更多on that and other tricks in this article
  • 新控制抽象(继续或休息)
  • 增强功能(Swing包装,性能......)

“重写代码”不是义务(除了使用一些改进的集合),但有一些功能,如 continuation Wikipedia:抽象表示控制状态,或“其余的计算”或“要执行的其余代码”)可以给你一些新的想法。一个很好的介绍是found here,由Daniel编写(他在这个帖子中也发布了很多more detailed and specific answer)。

注意:Scala on Netbeans似乎适用于2.8夜间构建(与official page for 2.7.x相比)

答案 2 :(得分:25)

VonC的答案很难改进,所以我甚至都不会尝试。我将介绍他未提及的其他一些内容。

首先,一些不赞成的东西会消失。如果您的代码中有弃用警告,则可能不再编译。

接下来,Scala的库正在扩展。通常,常见的小模式,例如将异常捕获到EitherOption,或将AnyRef转换为null映射到None的选项。这些东西大部分都可以忽略不计,但我已经厌倦了在博客上发布内容,后来有人告诉我它已经在Scala 2.8上了。嗯,实际上,我并没有感到厌倦,而是,幸运地,习惯了它。我不是在这里谈论收藏品, 正在进行重大修订。

现在,如果人们发布了这些图书馆改进的实际例子作为答案, 会很好。我很乐意提出所有这些答案。

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

此外,Scala的编译器正在被修改为能够为IDE提供快速的部分编译,这意味着我们可以期望它们变得更加“了解”Scala - 通过查询Scala编译器本身的代码。

一个很大的变化可能会被许多人忽视,尽管它会减少图书馆作家和用户的问题。现在,如果您写下以下内容:

package com.mystuff.java.wrappers

import java.net._

您导入的不是Java的net库,而是com.mystuff.java的{​​{1}}库,netcomcom.mystuff和{ {1}}都在范围内,com.mystuff.java可以在com.mystuff.java.wrappers内找到。使用Scala 2.8,只有java获得范围。由于有时您希望其余部分在Scope中,因此现在允许使用替代com.mystuff语法:

wrappers

相当于:

package

恰好将package com.mystuff.factories package ligthbulbs package com.mystuff.factories { package lightbulbs { ... } } 纳入范围。

答案 3 :(得分:11)

  

需要重写任何内容吗?

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

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

需要成为

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

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

答案 4 :(得分:6)

这是Eric Willigers的清单,自2.2以来一直使用Scala。其中一些内容似乎可以追溯到最近的用户。

  

*明确从外包装中导入*

     

假设我们有

package a
class B
  

更改

package a.c
class D extends B
  

package a.c
import a.B
class D extends B
  

package a
package c
class D extends B
  

*从外部包*

导入时使用完全限定的包名称      

假设我们有

package a.b
object O { val x = 1 }
  

更改

package a.b.c
import b.O.x
  

package a.b.c
import a.b.O.x
  

*在容器方法调用中显式指定类型参数时,添加新类型参数*

     

更改

list.map[Int](f)
  

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

更改

map.transform[Value](g)
  

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

*使用订购创建有序地图,而不是转换为有序*

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

*导入替换scala.collection.jcl的隐式转换*

     

*不可变地图.update变为.updated *

     

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

     

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

     

*使用scala.tools.nsc.Settings *时的类路径

     

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

     

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

     

替换

list.filter(that.f _)
  

list.filter(that f _)
  

list.filter(that.f(_))

&GT; &GT; &GT;

  

*从弃用的枚举方法迁移iterator map *   使用枚举方法values.iterator values.map

     

*从已弃用的Iterator.fromValues(a, b, c, d) * 迁移   使用Iterator(a, b, c, d)

     

*避免弃用类型Collection *   请改用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 <- ...)      

*避免使用逗号*