Smalltalk 如何在没有副本的情况下向后流式传输集合?

Smalltalk 如何在没有副本的情况下向后流式传输集合?,smalltalk,pharo,squeak,Smalltalk,Pharo,Squeak,我想知道如何在没有Pharo/Squeak副本的情况下向后流式传输集合 例如,要流式处理#(1 2 3)因此流式处理下一步返回3,然后返回2,然后返回1。我知道我可以使用收集反向读取流,但是反向拷贝。我脑子里有三个选择: 修改代码以使用#reverseDo: 使用Xtream 自流 使用一个实例变量collection创建RevertingCollection类作为sequenceablecollection的子类。现在定义这三种方法(实例端): 完成了。您现在可以执行以下操作: stream

我想知道如何在没有Pharo/Squeak副本的情况下向后流式传输集合


例如,要流式处理
#(1 2 3)
因此
流式处理下一步
返回
3
,然后返回
2
,然后返回
1
。我知道我可以使用
收集反向读取流
,但是
反向
拷贝。

我脑子里有三个选择:

  • 修改代码以使用
    #reverseDo:
  • 使用Xtream
  • 自流

  • 使用一个实例变量
    collection
    创建
    RevertingCollection
    类作为
    sequenceablecollection
    的子类。现在定义这三种方法(实例端):

    完成了。您现在可以执行以下操作:

    stream := (RevertingCollection new on: #(1 2 3)) readStream.
    
    你会得到

    stream next "3".
    stream next "2".
    stream next "1"
    
    您可以进一步实现该消息

    SequenceableCollection >> #reverseStream
        ^(RevertingCollection new on: self) readStream
    
    这样,一切都简化为

    #(1 2 3) reverseStream
    
    附录

    如评论中所述,此处缺少两个部分:

    1。实例创建方法(类端)

    通过此添加,上述方法应改写为:

    SequenceableCollection >> #reverseStream
        ^(RevertingCollection on: self) readStream
    
    注意:其他Smalltalk用户希望将此方法命名为
    #with all:

    2。以下复制方法:

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

    此方法需要支持反向读取流中的
    #next:

    您可以使用生成器:

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

    基本上,生成器允许您围绕任何代码段包装流接口

    物体是美丽的!:)的确这是关键,因为美学刺激学习和创造力。就个人而言,我会为集合添加一个类端
    withAll:
    方法和一个访问器(在实例端使用
    on:
    会让我想到流,不知道为什么-如果你担心封装,请将访问器放在“私有”协议中),但这是一个非常好的答案。:-)@我完全同意你的看法。为了简洁起见,我在回答中没有进一步详述。一个更完整的实现需要一些实例创建方法(如您建议的方法)加上支持
    \next:
    所需的实例
    \copyFrom:to:
    。今天晚些时候我可能会扩展我的答案。我不知道生成器是什么,所以我打开了一个新问题。哦,我刚刚看到生成器是一个基于块的流,存在于Pharo中。不用问。回答得很好。谢谢。我也没听说过发电机,但它看起来简单高效。不过,我真的建议你不要使用那些“非闲聊式”的缩写。Smalltalk是关于可读性的@卡彭特:如果这是生产代码,我当然会使用完整的变量名。但这是一个工作区的例子,所以简洁是一种美德,伊姆霍。我不同意这一点。代码简洁从来都不是一种美德(也许当你拼命想节省带宽时除外),为什么牺牲可读性和清晰性会改善一些对其他人来说是一个教学示例的东西呢?代码只写一次,但要读很多很多次——总是迎合代码读者,而不是作者。我遇到了太多的生产代码,这些代码本来是要在以后“为生产而清理”的。。。但我现在不再说教了,我相信你知道我的意思我喜欢选项1。事实上,我会在尝试使用任何花哨的方法之前考虑它。
    RevertingCollection >> #copyFrom: start to: stop
        | n |
        n := self size.
        copy := collection copyFrom: n - stop + 1 to: n - start + 1.
        ^self class on: copy
    
    | coll stream |
    coll := #(1 2 3).
    stream := Generator on: [:g | coll reverseDo: [:ea | g yield: ea]].
    stream next