Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The product method implemented using foldRight _can_ in fact terminate early #679

Open
georgms opened this issue Jul 29, 2023 · 0 comments

Comments

@georgms
Copy link

georgms commented Jul 29, 2023

The question is if the product2 method implemented using foldRight can terminate early with the result 0.0 if it encounters 0.0 in the list.

The method is defined here:

The answer given is no, it cannot terminate early:

No, this is not possible! The reason is because _before_ we ever call our function, `f`, we evaluate its argument, which in the case of `foldRight` means traversing the list all the way to the end. We need _non-strict_ evaluation to support early termination---we discuss this in chapter 5.

However, providing a second higher-order function that checks for an early termination + a return value for that case makes early termination possible. A crude implementation might look like this:

  def foldRight[A, B](as: List[A], z: B)(f: (A, B) => B)(abort: (A => (Boolean), B)): B = // Utility functions
    as match {
      case Nil => z
      case Cons(x, xs) => if (abort._1(x)) abort._2 else f(x, foldRight(xs, z)(f)(abort))
    }

  def product2(ns: List[Double]) =
    foldRight(ns, 1.0)(_ * _)((_ == 0.0, 0.0)) // `_ * _` is more concise notation for `(x,y) => x * y`; see sidebar

To wit:

class ListTest extends munit.FunSuite {
  test("product with 0 returns 0") {
    assertEquals(List.product2(List(1, 2, 3, 0, 4)), 0d)
  }

  test("product") {
    assertEquals(List.product2(List(1, 2, 3)), 6d)
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant