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

Renamed lazy foldRight to foldLazy, and made it stack-safe. #150

Merged
merged 11 commits into from
Feb 12, 2015

Conversation

non
Copy link
Contributor

@non non commented Feb 9, 2015

This method introduces a new data type, Fold[A]. This type
allows to programmer to decide whether to continue evaluating
the fold (and provide an appropriate continuation function),
or to return immediately.

This fixes #88

This method introduces a new data type, Fold[A]. This type
allows to programmer to decide whether to continue evaluating
the fold (and provide an appropriate continuation function),
or to return immediately.
@non non added the in progress label Feb 9, 2015
@non
Copy link
Contributor Author

non commented Feb 9, 2015

There are a few things I'd like feedback on with this PR:

  1. Is the new name (foldLazy) good or bad? The overloading of foldRight was not great -- in particular it caused problems with implicit syntax. We could alternately name it some variation of foldRight.
  2. How do you feel about Fold[_]? Is the Pass hack not worth the trouble? (It will only be useful when implementing methods like exists, forall, find, and so on.) Are the names OK?
  3. Do you like the overall method? I feel like this is a pretty elegant way to encode the benefits of foldr in Scala, while maintaining stack safety. What do you think?

def loop(it: Iterator[A], fs: List[B => B]): B =
if (it.hasNext) {
val a: A = it.next
val fb: Fold[B] = f(it.next)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

val fb: Fold[B] = f(a) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wow, great catch! What a horrible bug :/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was fooling around with variance annotations and pulled everything out to give manual type annotations -- obviously I failed to clean things up sufficiently.

@non
Copy link
Contributor Author

non commented Feb 9, 2015

As @xuwei-k's bug report shows, I need to add some tests to exercise this code.

*
* This method evaluates `b` lazily (in some cases it will not be
* needed), and returns a lazy value. For more information about how
* this method works see the documentation for Fold[_].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can add a "@see" for the scaladoc

@ceedubs
Copy link
Contributor

ceedubs commented Feb 9, 2015

@non Good work; I like this. Scalaz has had lots of issues with things like exists and forall not short-circuiting. In fact it looks like the rest (hopefully) were finally cleaned up just 2 days ago: scalaz/scalaz#896 (thanks, @xuwei-k!).

I think using this approach as the default on derived Foldable methods could really help prevent that sort of thing.

I'll hold off on a thumbsup until you've had a chance to write the tests you mentioned, but I wanted to say thanks for putting this together and let you know that I think it looks like a good approach.

These tests exercise Foldable -- in particular they ensure that
the List and Stream instances' foldLazy method is lazy and also
stack-safe.
@non
Copy link
Contributor Author

non commented Feb 9, 2015

@ceedubs Thanks for the feedback! I have some basic tests in, so I feel pretty good about this now.

@ceedubs
Copy link
Contributor

ceedubs commented Feb 10, 2015

👍

*
* This code searches an infinite stream for 77:
*
* val found: Lazy[Boolean] =
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit pedantic, but if we wrap the code here in {{{ ... }}} then ScalaDoc will treat it as preformatted text.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that's a good point.

These changes should address the comments raised by @tixxit
and @julien-truffaut.
@tixxit
Copy link

tixxit commented Feb 10, 2015

👍

This means that there are only two abstract methods in
Foldable[F] now: foldLeft and foldLazy.
There are also a few small changes to make the code a bit
more readable, but nothing major. At this point I think
the documentation for Foldable is about as good as I can
make it.
@stew
Copy link
Contributor

stew commented Feb 12, 2015

👍

Thanks for all the hard work on this @non, I think this is fantastic

mpilquist added a commit that referenced this pull request Feb 12, 2015
Renamed lazy foldRight to foldLazy, and made it stack-safe.
@mpilquist mpilquist merged commit be9c43d into master Feb 12, 2015
non added a commit that referenced this pull request Feb 12, 2015
I should have merged master into #150, which would have
caught this problem earlier. Mea culpa.
@non non deleted the topic/update-foldable branch February 18, 2015 22:20
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

Successfully merging this pull request may close these issues.

Stack safety of lazy version of foldRight for List
7 participants