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.

Reply via email to