Skip to content

Commit b363a4d

Browse files
authored
Merge pull request #97 from FRosner/patch-1
Replace nondeterministic performantTraversables
2 parents d78c8ea + 48d7803 commit b363a4d

File tree

2 files changed

+20
-25
lines changed

2 files changed

+20
-25
lines changed

src/main/scala/stdlib/Traversables.scala

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -511,23 +511,19 @@ object Traversables extends FlatSpec with Matchers with org.scalaexercises.defin
511511
intList.min should be(res3)
512512
}
513513

514-
/** You would choose `foldLeft`/`reduceLeft` or `foldRight`/`reduceRight` based on your mathematical goal. One other reason for deciding is performance - `foldLeft` generally has better performance since it uses tail recursion. This exercise will either work fine or you will receive a `StackOverflowError`:
514+
/** The naive recursive implementation of `reduceRight` is not tail recursive and would lead to a stack overflow if used on larger traversables.
515+
* However, `reduceLeft` can be implemented with tail recursion.
516+
*
517+
* To avoid the potential stack overflow with the naive implementation of `reduceRight` we can easily implement it based on `reduceLeft` by reverting the list and the inverting the reduce function.
518+
* The same applies for folding operations.
519+
*
520+
* There is also a `reduce` (and `fold`) available, which works exactly like `reduceLeft` (and `foldLeft`) and it should be the prefered method to call unless there is a strong reason to use `reduceRight` (or `foldRight`).
515521
*/
516-
def performantTraversables(res0: Boolean) {
517-
val MAX_SIZE = 1000000
518-
val reduceLeftStartTime = new java.util.Date
519-
(1 to MAX_SIZE) reduceLeft (_ + _)
520-
val reduceLeftEndTime = new java.util.Date
521-
522-
val reduceRightStartTime = new java.util.Date
523-
(1 to MAX_SIZE) reduceRight (_ + _)
524-
val reduceRightEndTime = new java.util.Date
525-
526-
val totalReduceLeftTime = reduceLeftEndTime.getTime - reduceLeftStartTime.getTime
527-
val totalReduceRightTime = reduceRightEndTime.getTime - reduceRightStartTime
528-
.getTime
529-
530-
(totalReduceRightTime > totalReduceLeftTime) should be(res0)
522+
def reduceRightAsReduceLeft(res0: Int, res1: Int, res2: Int) {
523+
val intList = List(5, 4, 3, 2, 1)
524+
intList.reduceRight((x, y) => x - y) should be(res0)
525+
intList.reverse.reduceLeft((x, y) => y - x) should be(res1)
526+
intList.reverse.reduce((x, y) => y - x) should be(res2)
531527
}
532528

533529
/** `transpose` will take a traversable of traversables and group them by their position in it's own traversable, e.g.:

src/test/scala/stdlib/TraversablesSpec.scala

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -441,15 +441,14 @@ class TraversablesSpec extends Spec with Checkers {
441441
)
442442
}
443443

444-
// FIXME: this test depends on runtime timing of code
445-
// def `performant traversals` = {
446-
// check(
447-
// Test.testSuccess(
448-
// Traversables.performantTraversables _,
449-
// false :: HNil
450-
// )
451-
// )
452-
// }
444+
def `reduceRight as reduceLeft` = {
445+
check(
446+
Test.testSuccess(
447+
Traversables.reduceRightAsReduceLeft _,
448+
3 :: 3 :: 3 :: HNil
449+
)
450+
)
451+
}
453452

454453
def `transpose function` = {
455454
check(

0 commit comments

Comments
 (0)