【问题标题】:how to stream a collection backwards without copies?如何在没有副本的情况下向后流式传输集合?
【发布时间】:2015-03-21 00:23:40
【问题描述】:

我想知道如何在 Pharo/Squeak 中将集合向后复制

例如,要流式传输#(1 2 3),所以stream next 返回3,然后是2,然后是1。我知道我可以只使用 collection reversed readStream,但 reversed 复制。

【问题讨论】:

    标签: smalltalk pharo squeak


    【解决方案1】:

    您可以使用生成器:

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

    基本上,生成器可让您将流式接口包裹在任何代码段上。

    【讨论】:

    • 我不知道生成器是什么,所以我提出了一个新问题。
    • 哦,我刚刚看到 Generator 是一个基于块的 Stream 并且存在于 Pharo 中。没必要问。非常好的答案。谢谢。
    • 也没有听说过Generators,但它看起来简单而高效。不过,我真的建议您不要使用那些“非 Smalltalk-like”的缩写。 Smalltalk 是关于可读性的。 ;-)
    • @AmosM.Carpenter:如果这是生产代码,我当然会使用完整的变量名。但这是一个工作区示例,所以简洁是一种美德,恕我直言。
    • 我不同意这一点。代码的简洁从来都不是一种美德(除非你拼命地试图节省带宽),为什么牺牲可读性和清晰度会改善作为其他人的教学示例的东西?代码只写一次,但要读很多很多次——总是迎合代码阅读者,而不是编写者。我遇到了太多本应在以后“为生产而清理”的生产代码......但我现在停止讲道,我相信你知道我的意思。 ;-)
    【解决方案2】:

    创建RevertingCollection 类作为SequeanceableCollection 的子类,并带有一个实例变量collection。现在定义这三个方法(实例端):

    on: aCollection
        collection := aCollection
    
    size
        ^collection size
    
    at: index
        ^collection at: self size - index + 1
    

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

    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
    

    附录

    正如 cmets 中所讨论的,这里缺少两部分:

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

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

    加上这个,上面的方法应该改写成:

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

    注意:其他 smalltalkers 更喜欢将此方法命名为 #withAll:

    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:

    【讨论】:

    • 物件很漂亮! :)
    • 确实如此。这很关键,因为美学可以激发学习和创造力。
    • 就个人而言,我会添加一个类端 withAll: 方法和一个集合访问器(在实例端使用 on: 让我想到流,不知道为什么 - 如果你'担心封装,将访问器放在“私有”协议中),但这是一个非常好的答案。 :-)
    • @AmosM.Carpenter 我完全同意你的看法。为了简洁起见,我没有在回答中进一步详细说明。更完整的实现将需要一些实例创建方法(如您所建议的那样)以及支持#next: 所需的实例#copyFrom:to:。我可能会在今天晚些时候扩展我的答案。
    【解决方案3】:

    我想到了三个选项:

    1. 修改您的代码以使用#reverseDo:
    2. 使用 Xtreams
    3. 滚动您自己的信息流

    【讨论】:

    • 我喜欢选项 1。事实上,在尝试使用任何花哨的方法之前我会考虑它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-08
    • 1970-01-01
    • 2015-06-22
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多