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

Improve traverseViaChain API #3535

Merged
merged 5 commits into from
Aug 3, 2020
Merged

Conversation

johnynek
Copy link
Contributor

follow up to #3521

In that PR, I added an API that consumes an Iterator. That is a bummer to have an API with a mutable arg, even if most people know that iterators must be considered with ownership semantics.

In fact, the first thing we do is materialize an IndexedSeq, so, why not just take an IndexedSeq and have callers materialize one if needed. This also removes duplication since Vector can share the same implementation now.

As an added bonus, you can use Chain.traverseViaChain(0 until 100000)(f) since Range is an IndexedSeq as well, which is nice.

It would be nice to get this in before 2.2.0 so we aren't stuck with the mutable API.

@johnynek
Copy link
Contributor Author

@travisbrown I know I'm making your life a pain here with these PRs. I'm sorry. I do hope we can get this in and not have mima force us to keep an unneeded mutable API.

@travisbrown
Copy link
Contributor

No, this is great. Happy to review in the morning.

@codecov-commenter
Copy link

codecov-commenter commented Jul 28, 2020

Codecov Report

Merging #3535 into master will increase coverage by 0.07%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master    #3535      +/-   ##
==========================================
+ Coverage   91.34%   91.41%   +0.07%     
==========================================
  Files         386      386              
  Lines        8592     8540      -52     
  Branches      241      241              
==========================================
- Hits         7848     7807      -41     
+ Misses        744      733      -11     

@johnynek
Copy link
Contributor Author

Okay, the 2.13 build brought up an interesting issue:

in 2.12, IndexedSeq is collection.IndexedSeq which may be mutable, which accepts ArrayBuffer. But that isn't safe for a lazy Applicative, because the computation may run later and the caller could mutate the input still. So, I added a wrapper which just makes an immutable.IndexedSeq from a mutable one when the caller promises not to mutate. Then, the public API can require an immutable IndexedSeq, which makes the contract clear.

This is probably a minor performance hit, but I imagine very very minimal (since the real meat of what traverse is doing is still the Eval and the applicative context I assume.

I think I'm happy with this now if you can take a look @travisbrown

@johnynek
Copy link
Contributor Author

johnynek commented Aug 3, 2020

@travisbrown what do you think about this one?

Copy link
Contributor

@travisbrown travisbrown left a comment

Choose a reason for hiding this comment

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

Looks fine to me!

def wrapMutableIndexedSeq[A](m: mutable.IndexedSeq[A]): ImIndexedSeq[A] =
new WrappedIndexedSeq(m)

private[kernel] class WrappedIndexedSeq[A](m: mutable.IndexedSeq[A]) extends ImIndexedSeq[A] {
Copy link
Contributor

Choose a reason for hiding this comment

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

I can never remember exactly how this works inside objects, but is there any reason to make this package-private (which is just public in the JVM API) instead of just private (which I think should be properly JVM-private)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not that I know of, I just copied the idiom below. Should I fix that up?

@@ -508,11 +500,11 @@ sealed abstract class Chain[+A] {
val builder = new StringBuilder("Chain(")
var first = true

foreach { a =>
foreachUntil { a =>
Copy link
Contributor

Choose a reason for hiding this comment

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

This is just miscellaneous clean-up, right, since foreach isn't used anywhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes. foreach is used exactly once and is private. Just use foreachUntil (or iterator).

@johnynek johnynek merged commit 763847f into master Aug 3, 2020
@travisbrown travisbrown added this to the 2.2.0-RC3 milestone Aug 15, 2020
@larsrh larsrh deleted the oscar/improveTraverseViaChain branch September 19, 2020 07:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants