-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Add unit test to verify Chain.zipWithIndex stack safety #3373
Add unit test to verify Chain.zipWithIndex stack safety #3373
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍, this might be my fault. Good catch, and thanks for implementing it. Do you mind adding a test?
@@ -331,7 +331,7 @@ sealed abstract class Chain[+A] { | |||
case Singleton(a) => Singleton((a, 0)) | |||
case Append(left, right) => | |||
val leftSize = left.length.toInt | |||
Append(left.zipWithIndex, right.zipWithIndex.map { case (a, i) => (a, leftSize + i) }) | |||
Wrap(left.toList.zipWithIndex ++ right.toList.zipWithIndex.map { case (a, i) => (a, leftSize + i) }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason not to use a .toVector
or something else that ++
's better than List
here?
ca03f32
to
f8467cd
Compare
Sorry appalling response time on this. The arbitrary instance here is used all over the Also I only force pushed, github making me sound sassy 💁♂️
|
The failure here is just styling, you probably just need to re-run |
@@ -333,7 +333,7 @@ sealed abstract class Chain[+A] { | |||
case Singleton(a) => Singleton((a, 0)) | |||
case Append(left, right) => | |||
val leftSize = left.length.toInt | |||
Append(left.zipWithIndex, right.zipWithIndex.map { case (a, i) => (a, leftSize + i) }) | |||
Wrap(left.toVector.zipWithIndex ++ right.toVector.zipWithIndex.map { case (a, i) => (a, leftSize + i) }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not:
case a@Append(_, _) =>
val it = a.iterator
Wrap(it.zip(Iterator.iterate(0)(_ + 1)).toList)
this way, we only materialize one new list and leverage the existing iterator code. The code above materializes to vector (.toVector), one of them is copies again: (.map(... leftSize + i) })
, then copies them (.zipWithIndex) then concats them (++).
So, there are like 6 materializations of the values. the iterator approach I suggest above does just one.
I think the current master's version resolve this issue, but the test in here is still a valuable addition IMO. @dantb, I was wondering if you have some steam left to resolve the conflicts. Either way thanks a lot for your contribution. |
f8467cd
to
7f51dd7
Compare
Rebased and repurposed - thanks @barambani |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks!
Thanks again. |
Noticed while poking around to add
zipAll
thatzipWithIndex
onChain
(also called fromNonEmptyChain
) isn’t tail recursive. It’ll blow the stack if the chain is built from manyconcat
s meaning we have a highly nestedAppend
structure. E.g.This wasn’t caught by tests as the arbitrary instances generate only small collections - I guess this was a conscious decision?
Either way worth flagging 😄
Edit: has since been fixed in #3533 so this change only adds a unit test. Changed title to reflect that.