how to stream a collection backwards without copie

2019-04-29 07:34发布

I would like to know how to stream a collection backwards without copies in Pharo/Squeak.

For example, to stream #(1 2 3) so stream next returns 3, then 2, then 1. I know I could just use collection reversed readStream, but reversed copies.

3条回答
霸刀☆藐视天下
2楼-- · 2019-04-29 08:18

Create the RevertingCollection class as a subclass of SequeanceableCollection with one instance variable collection. Now define these three methods (instance side):

on: aCollection
    collection := aCollection

size
    ^collection size

at: index
    ^collection at: self size - index + 1

Done. You can now do the following:

stream := (RevertingCollection new on: #(1 2 3)) readStream.

and you will get

stream next "3".
stream next "2".
stream next "1"

You can go a step further and implement the message

SequenceableCollection >> #reverseStream
    ^(RevertingCollection new on: self) readStream

In this way everything reduces to just

#(1 2 3) reverseStream

ADDENDUM

As discussed in the comments there are two pieces missing here which are:

1. An instance creation method (class side)

RevertingCollection class >> #on: aCollection
    ^self new on: aCollection

With this addition the method above should be rewritten to:

SequenceableCollection >> #reverseStream
    ^(RevertingCollection on: self) readStream

Note: Other smalltalkers would prefer this method to be named #withAll:.

2. The following method for copying:

RevertingCollection >> #copyFrom: start to: stop
    | n |
    n := self size.
    copy := collection copyFrom: n - stop + 1 to: n - start + 1.
    ^self class on: copy

This method is required to support #next: in the reverse read stream.

查看更多
该账号已被封号
3楼-- · 2019-04-29 08:19

There are three options off the top of my head:

  1. Modify your code to use #reverseDo:
  2. Use Xtreams
  3. Roll your own stream
查看更多
女痞
4楼-- · 2019-04-29 08:23

You could use a Generator:

| coll stream |
coll := #(1 2 3).
stream := Generator on: [:g | coll reverseDo: [:ea | g yield: ea]].
stream next

Generators let you wrap a streaming interface around any piece of code, basically.

查看更多
登录 后发表回答