summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorSimon Ochsenreither <simon@ochsenreither.de>2016-04-27 21:25:57 +0200
committerSimon Ochsenreither <simon@ochsenreither.de>2016-05-27 15:01:47 +0200
commit6e9faf5157132ad575c98e5a9a0919ac38b7beb8 (patch)
tree1230333b98544c28b26e7c9e55d7581c62f323bd /test
parentf7b575de222befb2cd1dd2f676e177ece8a1d234 (diff)
downloadscala-6e9faf5157132ad575c98e5a9a0919ac38b7beb8.tar.gz
scala-6e9faf5157132ad575c98e5a9a0919ac38b7beb8.tar.bz2
scala-6e9faf5157132ad575c98e5a9a0919ac38b7beb8.zip
Right-bias Either
- Add operations like map, flatMap which assume right-bias - Deprecate {Left,Right}Projection - Deprecate left and right in favor of swap - Add contains, toOption, toTry, toSeq and filterOrElse - toSeq returns collection.immutable.Seq instead of collection.Seq - Don't add get There are no incompatible changes. The only possibility of breakage that exists is when people have added extension methods named map, flatMap etc. to Either in the past doing something different than the methods added to Either now. One detail that moved the scales in favor of deprecating LeftProjection and RightProjection was the desire to have toSeq return scala.collection.immutable.Seq instead of scala.collection.Seq like LeftProjection and RightProjection do. Therefore keeping LeftProjection and RightProjection would introduce inconsistency. filter is called filterOrElse because filtering in a for-comprehension doesn't work if the method needs an explicit argument. contains was added as safer alternative to if (either.isRight && either.right.get == $something) ... While adding filter with an implicit zero value is possible, it's dangerous as it would require that developers add a "naked" implicit value of type A to their scope and it would close the door to a future in which the Scala standard library ships with Monoid and filter could exist with an implicit Monoid parameter.
Diffstat (limited to 'test')
-rw-r--r--test/files/presentation/doc/doc.scala6
-rw-r--r--test/files/presentation/t7678/Runner.scala2
-rw-r--r--test/files/scalacheck/CheckEither.scala70
3 files changed, 71 insertions, 7 deletions
diff --git a/test/files/presentation/doc/doc.scala b/test/files/presentation/doc/doc.scala
index ce431910ee..8c60af557b 100644
--- a/test/files/presentation/doc/doc.scala
+++ b/test/files/presentation/doc/doc.scala
@@ -62,7 +62,7 @@ object Test extends InteractiveTest {
def getComment(sym: Symbol, source: SourceFile, fragments: List[(Symbol,SourceFile)]): Option[Comment] = {
val docResponse = new Response[(String, String, Position)]
askDocComment(sym, source, sym.owner, fragments, docResponse)
- docResponse.get.left.toOption flatMap {
+ docResponse.get.swap.toOption flatMap {
case (expanded, raw, pos) =>
if (expanded.isEmpty)
None
@@ -85,13 +85,13 @@ object Test extends InteractiveTest {
val batch = new BatchSourceFile(source.file, newText.toCharArray)
val reloadResponse = new Response[Unit]
compiler.askReload(List(batch), reloadResponse)
- reloadResponse.get.left.toOption match {
+ reloadResponse.get.swap.toOption match {
case None =>
println("Couldn't reload")
case Some(_) =>
val parseResponse = new Response[Tree]
askParsedEntered(batch, true, parseResponse)
- parseResponse.get.left.toOption match {
+ parseResponse.get.swap.toOption match {
case None =>
println("Couldn't parse")
case Some(_) =>
diff --git a/test/files/presentation/t7678/Runner.scala b/test/files/presentation/t7678/Runner.scala
index 14d6dc2a70..c6736a65b0 100644
--- a/test/files/presentation/t7678/Runner.scala
+++ b/test/files/presentation/t7678/Runner.scala
@@ -7,7 +7,7 @@ object Test extends InteractiveTest {
override def runDefaultTests() {
def resolveTypeTagHyperlink() {
- val sym = compiler.askForResponse(() => compiler.currentRun.runDefinitions.TypeTagClass).get.left.get
+ val sym = compiler.askForResponse(() => compiler.currentRun.runDefinitions.TypeTagClass).get.swap.getOrElse(???)
val r = new Response[Position]
compiler.askLinkPos(sym, new BatchSourceFile("", source), r)
r.get
diff --git a/test/files/scalacheck/CheckEither.scala b/test/files/scalacheck/CheckEither.scala
index 48f732a22d..f0ec797045 100644
--- a/test/files/scalacheck/CheckEither.scala
+++ b/test/files/scalacheck/CheckEither.scala
@@ -132,6 +132,58 @@ object Test extends Properties("Either") {
case Right(a) => a
}))
+ val prop_getOrElse = forAll((e: Either[Int, Int], or: Int) => e.getOrElse(or) == (e match {
+ case Left(_) => or
+ case Right(b) => b
+ }))
+
+ val prop_contains = forAll((e: Either[Int, Int], n: Int) =>
+ e.contains(n) == (e.isRight && e.right.get == n))
+
+ val prop_forall = forAll((e: Either[Int, Int]) =>
+ e.forall(_ % 2 == 0) == (e.isLeft || e.right.get % 2 == 0))
+
+ val prop_exists = forAll((e: Either[Int, Int]) =>
+ e.exists(_ % 2 == 0) == (e.isRight && e.right.get % 2 == 0))
+
+ val prop_flatMapLeftIdentity = forAll((e: Either[Int, Int], n: Int, s: String) => {
+ def f(x: Int) = if(x % 2 == 0) Left(s) else Right(s)
+ Right(n).flatMap(f(_)) == f(n)})
+
+ val prop_flatMapRightIdentity = forAll((e: Either[Int, Int]) => e.flatMap(Right(_)) == e)
+
+ val prop_flatMapComposition = forAll((e: Either[Int, Int]) => {
+ def f(x: Int) = if(x % 2 == 0) Left(x) else Right(x)
+ def g(x: Int) = if(x % 7 == 0) Right(x) else Left(x)
+ e.flatMap(f(_)).flatMap(g(_)) == e.flatMap(f(_).flatMap(g(_)))})
+
+ val prop_mapIdentity = forAll((e: Either[Int, Int]) => e.map(x => x) == e)
+
+ val prop_mapComposition = forAll((e: Either[Int, String]) => {
+ def f(s: String) = s.toLowerCase
+ def g(s: String) = s.reverse
+ e.map(x => f(g(x))) == e.map(x => g(x)).map(f(_))})
+
+ val prop_filterOrElse = forAll((e: Either[Int, Int], x: Int) => e.filterOrElse(_ % 2 == 0, -x) ==
+ (if(e.isLeft) e
+ else if(e.right.get % 2 == 0) e
+ else Left(-x)))
+
+ val prop_seq = forAll((e: Either[Int, Int]) => e.toSeq == (e match {
+ case Left(_) => collection.immutable.Seq.empty
+ case Right(b) => collection.immutable.Seq(b)
+ }))
+
+ val prop_option = forAll((e: Either[Int, Int]) => e.toOption == (e match {
+ case Left(_) => None
+ case Right(b) => Some(b)
+ }))
+
+ val prop_try = forAll((e: Either[Throwable, Int]) => e.toTry == (e match {
+ case Left(a) => util.Failure(a)
+ case Right(b) => util.Success(b)
+ }))
+
/** Hard to believe I'm "fixing" a test to reflect B before A ... */
val prop_Either_cond = forAll((c: Boolean, a: Int, b: Int) =>
Either.cond(c, a, b) == (if(c) Right(a) else Left(b)))
@@ -169,9 +221,21 @@ object Test extends Properties("Either") {
("prop_Either_right", prop_Either_right),
("prop_Either_joinLeft", prop_Either_joinLeft),
("prop_Either_joinRight", prop_Either_joinRight),
- ("prop_Either_reduce", prop_Either_reduce),
- ("prop_Either_cond", prop_Either_cond)
- )
+ ("prop_Either_reduce", prop_Either_reduce),
+ ("prop_getOrElse", prop_getOrElse),
+ ("prop_contains", prop_contains),
+ ("prop_forall", prop_forall),
+ ("prop_exists", prop_exists),
+ ("prop_flatMapLeftIdentity", prop_flatMapLeftIdentity),
+ ("prop_flatMapRightIdentity", prop_flatMapRightIdentity),
+ ("prop_flatMapComposition", prop_flatMapComposition),
+ ("prop_mapIdentity", prop_mapIdentity),
+ ("prop_mapComposition", prop_mapComposition),
+ ("prop_filterOrElse", prop_filterOrElse),
+ ("prop_seq", prop_seq),
+ ("prop_option", prop_option),
+ ("prop_try", prop_try),
+ ("prop_Either_cond", prop_Either_cond))
for ((label, prop) <- tests) {
property(label) = prop