如何在Swift中共享文本函数之间的流位置



在看到代码中的一些意外行为后,我对创建的以下游乐场感到惊讶:

import Foundation
let bytes:[UInt8] = [20, 30, 40, 50, 60, 70]
var stream = bytes.generate()
func consumeTwo(var stream:IndexingGenerator<[UInt8]>) {
    print(stream.next())
    print(stream.next())
}
consumeTwo(stream) // This prints 20 and 30
print(stream.next()) // This prints 20!? I expected 40!

我曾认为,将stream参数标记为varconsumeTwo()函数,流状态/位置将在从一个函数移动到另一个函数时共享/更新。但事实似乎并非如此。

这是否意味着我需要使其成为inout?然后用安培数通过?如果是这样的话,什么时候使用var

更普遍地说。。。在字节数组上创建流的正确/惯用方法是什么?字节数组可以从一个函数传递到另一个函数(例如解码器),并在传递时保留流的位置?

+1表示问题标题中的古英语。:)

在函数签名中使用var时,将创建该值的本地副本。这和你这样做是一样的:

func consumeTwo(stream: IndexingGenerator<[UInt8]>) {
    var localStream = stream
    print(localStream.next())
    print(localStream.next())
}

当参数是引用类型(即类)时,重复的"值"是对同一对象的重复引用。但是从Array.generate()得到的是一个值类型,所以本地副本是一个具有独立状态的独立迭代器。

这是否意味着我需要使其成为inout?然后用安培数通过?

是的——对于您的简单示例,inout(并与&一起传递)是一种简单而惯用的方法:

func consumeTwo(inout stream:IndexingGenerator<[UInt8]>) {
    print(stream.next())
    print(stream.next())
}
consumeTwo(&stream) // This prints 20 and 30
print(stream.next()) // This prints 40

请记住:当您想修改函数边的值类型in,然后再查看函数边的out修改时,请使用inout&也随之而来,因此无论是在函数内部还是在调用站点,都可以清楚地看到这种行为正在发生。

如果是这样的话,什么时候使用var

仅当您希望制作函数调用的本地副本时,才对参数使用var。诚然,这方面的用例很少。这是一个人为的(完全没有必要的):

func bananify(var strings: [String]) {
    for i in 1.stride(to: strings.count, by: 2) {
        strings[i] = "banana"
    }
    print(strings.joinWithSeparator(" "))
}
let words = ["foo", "bar", "bas", "zap", "asdf"]
bananify(words) // "foo banana bas banana asdfn"

如果你觉得这令人困惑,你不是唯一一个。因此,取消使用var作为参数的功能是Swift 3的一项计划更改。

更普遍地说。。。在字节数组上创建流的正确/惯用方法是什么?字节数组可以从一个函数传递到另一个函数(例如解码器),并在传递时保留流的位置?

正如user3441734所指出的,您确实可以创建并使用引用类型迭代器。或者,您可以编写一个引用类型来保存和管理迭代器。对于在程序的几个子系统之间共享流的假设情况,这可能是一种很好的方法——表示共享资源是使用引用类型的规范情况之一。

你写道:"这让我希望生成器是对象而不是结构。"

将某些生成器定义为引用类型是没有问题的。。。

class G: AnyGenerator<Int> {
    var i = 0
    override func next() -> Int? {
        return i++
    }
}
let g = G()
func foo(gen: G)->Void {
    print(gen.next())
    print(gen.next())
}
foo(g)
print(g.next())
/*
Optional(0)
Optional(1)
Optional(2)
*/

相关内容

  • 没有找到相关文章

最新更新