Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Sequences by
edited by

2 problems:
- The docstring of clojure.core/partition is not clear on what "last partition" means.
- The behavior of partition is strange, IHMO it has a bug.

Please take a look at this:

(partition 3 1 [:a :b :c] (range 5))

; actual behavior
; => ((0 1 2) (1 2 3) (2 3 4) (3 4 :a))

; expected behavior, option 1
; => ((0 1 2) (1 2 3) (2 3 4))

; expected behavior, option 2
; => ((0 1 2) (1 2 3) (2 3 4) (3 4 :a) (4 :a :b))

I would expect the "last partition" to be defined as:

The last partition to contain elements from the input collection (not the padding collection) which are not present in any previous partition.

This is consistent with option 1 above.

2 Answers

+1 vote

Option 2 can be dismissed because, whatever "last partition" might mean, there can be only one "last partition", and only it can draw from the padding collection.

The docstring says "If a pad collection is supplied [and] there are not enough padding elements, return a partition with less than n items", so Option 1 can also be dismissed.

How would you clarify the docstring?

Zero padding elements is less than n items. I don't see any problem with the option 1.

I updated my question to include my suggested definition for "last partition".
+1 vote

partition is making full partitions of N elements. if it can't make a full partition, you're done. if you supply a pad coll, it will use that to complete the first partition where it can't make a full partition (which will be the last partition).

  • option 1 is the expected behavior when there is no pad coll (stop when you can't make a full partition), but here there is a pad coll
  • option 2 would make multiple (<N) partitions, so no.

I can understand #2 as a possible interpretation (esp compared with partition-all behavior for same), but I think changing the current behavior would potentially be a breaking change for existing users.

I strongly feel that my question is being misunderstood.

The problem that I am trying to point here exists when we call the `partition` function with a custom value for the `step` parameter (a value which is different than `n`). So far, no answer mentioned about the `step` parameter.
I am not a member of the Clojure core team, so cannot speak for them, but I can say that they definitely value backwards compatibility of behavior for core functions.  Given that the current behavior of `partition` has been the way it currently is for at least 10 years, they are likely loathe to change its behavior, in case any working code out there relies upon it, in all of its details.

If that is the situation, then the core team is far more likely to consider changes to the documentation that clarifies this existing behavior, rather than changing the behavior.

There are also sites like https://clojuredocs.org/clojure.core/partition that allow community-contributed examples of behavior of core functions, with comments explaining it, that allow far more extensive examples than most Clojure core functions will likely ever include in their doc strings.
The `step` parameter isn't relevant to the described behavior: (partition n coll) just means (partition n n coll), i.e., partition with a step of n, so it _always_ has a step value and that just determines how many elements are skipped in coll before starting the next partition. What Alex has described as the behavior is not affected by the step value.

The pad collection only matters if the last partition that would be generated doesn't have n items in it:

dev=> (partition 3 3 [:a :b :c] (range 5))

((0 1 2) (3 4 :a))

dev=> (partition 3 3 (range 5))

((0 1 2))

dev=> (partition 3 2 [:a :b :c] (range 5))

((0 1 2) (2 3 4) (4 :a :b))

dev=> (partition 3 2 (range 5))

((0 1 2) (2 3 4))

dev=> (partition 3 1 [:a :b :c] (range 5))

((0 1 2) (1 2 3) (2 3 4) (3 4 :a))

dev=> (partition 3 1 (range 5))

((0 1 2) (1 2 3) (2 3 4))