My own Smalltalk has these:

Enumerable
�� methods for: 'enumerating'
������ limit: n do: aBlock
���������� "Pass elements of the receiver to aBlock one at a time,
������������ as for #do:, but stop after n elements.�� n must be a
������������ non-negative SmallInteger.�� Which elements you get is
������������ for the receiver to decide."
���������� |count|
���������� n < 1 ifTrue: [
�������������� n = 0 ifTrue: [^self]ifFalse: [self pvtCountError: n]].
���������� count := 0.
���������� self do: [:each |
�������������� aBlock value: each.
�������������� (count := count + 1) < n ifFalse: [^self]].
AbstractKeyedCollection
�� methods for: 'enumerating'
������ limit: n keysAndValuesDo: aBlock����
���������� "Pass keys and corresponding values of the receiver
������������ to aBlock one at a time, as for #keysAndValuesDo:,
������������ but stop after n elements.�� See #limit:do:."
���������� |count|
���������� n < 1 ifTrue: [
�������������� n = 0 ifTrue: [^self]ifFalse: [self pvtCountError: n]].
���������� count := 0.
���������� self keysAndValuesDo: [:key :value |
�������������� aBlock value: key value: value.
�������������� (count := count + 1) < n ifFalse: [^self]].


Enumerable is the superclass of Collection; it doesn't cover streams but does
cover 2- and 3-dimensional arrays.�� AbstractKeyedCollection covers both
dictionaries and sequences. Since they only depend on #do: and #keysAndValuesDo:
respectively, they should fit nicely into some sort of Trait(s).

I gave a great deal of thought to the names, and decided on "limit" since it
is already in use in a similar sense in things like LimitedOutputStream or
#printStringLimitedTo:.�� I did consider #do:limitedTo: and #keysAndValuesDo:limitedTo:
which would be more consistent with #streamContents:limitedTo:, but "heavy" things
like blocks really work better at the end.