MultiProductArray/iproduct_arr #286
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #264.
I've added a new macro,
iproduct_arr
, which can be called in the same way asiproduct
(but only when all iterators are the same type) or using the[iter; count]
format, as requested in the issue.The macro uses a new underlying type,
MultiProductArray
, which is like aMultiProduct
but yields arrays instead of vecs. The short-form macro uses arepeat_n
rather than macro-based repetition, so there shouldn't be any tricky ownership/multiple-mutation issues.I did consider using something similar to the combination of
ConsTuples
+Product
whichiproduct
uses, but found that utilisingMultiProduct
as a base was a better fit. The tradeoffs of this decision are as follows:MultiProductArray
without using the macro, and in this case use a meta-iterator as the source, as long as the number of produced sub-iterators is known at compile-time. (e.g.(0..3).map(|i| 0..i)
).fold()
(and still many times faster than the vec-basedMultiProduct
). I haven't benched with types which allocate heap memory.Creating a
MultiProductArray
manually requires the user to specify an array type parameter with length matching the number of sub-iterators. It uses a trait, implemented only on array types, to assert that this length is correct upon construction. The trait is "public-private", so that it cannot be implemented by users.I've updated the documentation for
iproduct
andmulti_cartesian_product
to compare them withiproduct_arr
.While adding quickcheck tests, I refactored the main tests for
Product
,MultiProduct
andMultiProductArray
to use the same underlying function.MultiProduct
's test should be functionally identical to before, whilstProduct
now has slightly different input variables, and additionally tests.last()
.During development, I ended up doing a fairly significant refactor of
MultiProduct
. The original reason for this was a potential performance improvement; however I didn't realise that the improvement is not possible on rustc 1.12 (without further impl type restrictions). As a result, the current implementation would probably work without this refactor. So there are probably more changes for you to review than strictly necessary... but it does also introduce a ~5% speed increase forMultiProduct
:)Also, I added a match-arm to both
iproduct
andiproduct_arr
to allow trailing commas.As always, let me know if there are any API/syntax changes that you think should be made, plus any other issues you see with the aforementioned changes.