Каковы самые большие различия между Scala 2.8 и Scala 2.7?
Я написал довольно большую программу на Scala 2.7.5, и теперь я с нетерпением жду версии 2.8. Но мне любопытно, как этот большой скачок в эволюции Scala повлияет на меня.
Каковы будут самые большие различия между этими двумя версиями Scala? И, возможно, самое главное:
- Нужно ли будет что-нибудь переписывать?
- Хочу ли я что-нибудь переписать, просто чтобы воспользоваться какой-нибудь интересной новой функцией?
- Каковы именно новые функции Scala 2.8 в целом?
5 ответов
Вы можете найти здесь предварительный просмотр новой функции в Scala2.8 (апрель 2009 г.), дополненной недавно этой статьей (июнь 2009 г.)
- Именованные и стандартные аргументы
- Вложенные аннотации
- Пакет объектов
- @specialized
- Улучшенные коллекции (здесь может потребоваться некоторая перезапись)
- У REPL будет завершение команды (подробнее об этом и других приемах в этой статье)
- Новые контрольные абстракции (продолжение или перерыв)
- Улучшения (Swing wrapper, перформансы,...)
"Переписать код" не является обязательным (за исключением использования некоторых улучшенных коллекций), но некоторые функции, такие как продолжение ( Википедия: абстрактное представление состояния элемента управления, или "остальная часть вычислений" или "остальная часть кода, который должен быть выполнен) ") может дать вам несколько новых идей. Хорошее введение можно найти здесь, написанное Daniel C. Sobral (который также опубликовал более подробный и конкретный ответ в этой теме).
Примечание. Похоже, что Scala на NetBeans работает с 2.8 ночной сборкой (по сравнению с официальной страницей 2.7.x).
Принимая прыжок
Когда вы мигрируете, компилятор может предоставить вам несколько сетей безопасности.
- Скомпилируйте ваш старый код с 2.7.7 с
-deprecation
и следуйте рекомендациям всех предупреждений об устаревании. Обновите свой код, чтобы использовать ненесненные пакеты. Это можно сделать механически, многократно выполняя это регулярное выражение поиска замены.
s/^(package com.example.project.*)\.(\w+)/$1\npackage $2/g
Компилировать с компилятором 2.8.0, используя параметры командной строки paranoid
-deprecation -Xmigration -Xcheckinit -Xstrict-warnings -Xwarninit
Если вы получаете ошибки, ошибка
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
в качестве параметра типа также должен принимать манифест в качестве неявного параметра. Смотрите SID массива для деталей.Вскоре вы столкнетесь с такой ошибкой:
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
, но это действительно деталь реализации.
Пожинать плоды
- Замените перегрузку некоторых методов именованными параметрами и параметрами по умолчанию.
Используйте сгенерированный
copy
метод кейс-классов.scala> case class Foo(a: Int, b: String) defined class Foo scala> Foo(1, "a").copy(b = "b") res1: Foo = Foo(1,b)
- Обобщите ваши подписи метода от
List
вSeq
или жеIterable
или жеTraversable
, Поскольку классы коллекции находятся в чистой иерархии, вы можете принять более общий тип. - Интеграция с библиотеками Java с помощью аннотаций. Теперь вы можете указывать вложенные аннотации и иметь детальный контроль над тем, нацелены ли аннотации на поля или методы. Это помогает использовать Spring или JPA с кодом Scala.
Есть много других новых функций, которые можно безопасно игнорировать при начале миграции, например @specialized
и продолжения.
Ответ VonC сложно улучшить, поэтому я даже не буду пытаться. Я расскажу о некоторых других вещах, не упомянутых им.
Во-первых, некоторые устаревшие вещи пойдут. Если в вашем коде есть предупреждения об устаревании, скорее всего, он больше не будет компилироваться.
Затем библиотека Scala расширяется. В основном, общие маленькие шаблоны, такие как перехват исключений в Either
или же Option
или преобразование AnyRef в Option с 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
"s net
библиотека, как com
, com.mystuff
, com.mystuff.java
а также com.mystuff.java.wrappers
все попало в сферу, и java
можно найти внутри com.mystuff
, Только с Scala 2.8 wrappers
получает объем. Поскольку иногда вы хотите, чтобы часть остальных была в Scope, альтернативе package
синтаксис теперь разрешен:
package com.mystuff.factories
package ligthbulbs
что эквивалентно:
package com.mystuff.factories {
package lightbulbs {
...
}
}
И случается, чтобы получить оба factories
а также lightbulbs
в сферу.
Нужно ли будет что-нибудь переписывать?
def takesArray(arr: Array[AnyRef]) {…}
def usesVarArgs(obs: AnyRef*) {
takesArray(obs)
}
должен стать
def usesVarArgs(obs: AnyRef*) {
takesArray(obs.toArray)
}
Мне пришлось посетить канал IRC для этого, но потом понял, что я должен был начать здесь.
Вот контрольный список от Эрика Виллигерса, который использует Scala с 2.2. Некоторые из этих материалов покажутся более поздними пользователями.
* Явный импорт из внешних пакетов *
Предположим, у нас есть
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
* classpath при использовании scala.tools.nsc.Settings *
http://thread.gmane.org/gmane.comp.lang.scala/18245/focus=18247 settings.classpath.value = System.getProperty ("java.class.path")
* Избегайте ошибок: _ должен следовать методу; не может следовать (Any) => Boolean *
замещать
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)
* Избегайте устаревшего типа
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 <- ...)
** Избегайте запятых *