为什么Swift数组插入和removeAtIndex操作表现不一致?

时间:2014-08-02 15:35:02

标签: ios arrays swift

我认为交换Swift数组的第0项和第1项是合法的,如下所示:

  • 在索引0处调用removeAtIndex,将第一项重新洗回到索引0
  • 在索引1处插入已删除的项目。

但我看到不一致的行为取决于我如何编码。

代码

func test() {

    class Test {

        var array = ["foo", "bar"]

        func swap1() {       // PRODUCES STRANGE RESULT
            array.insert(array.removeAtIndex(0), atIndex:1)
            print("---swap1---", xs:array)
        }

        func swap2() {       // PRODUCES EXPECTED RESULT
            let item = array.removeAtIndex(0)
            array.insert(item, atIndex:1)
            print("---swap2---", xs:array)
        }

        func swap3() {       // PRODUCES EXPECTED RESULT
            var array = ["foo", "bar"]
            array.insert(array.removeAtIndex(0), atIndex:1)
            print("---swap3---", xs:array)
        }

        func print(fn: String, xs: [String]) {
            println(fn)
            for x in xs { println(x) }
        }
    }

    Test().swap1()
    Test().swap2()
    Test().swap3()
}

输出

---swap1---
foo
foo
bar
---swap2---
bar
foo
---swap3---
bar
foo

出乎意料地(对我来说),swap1()克隆第0个元素而不是删除它,从重复的" foo"在上面的swap1输出中。似乎产生这种行为的特征是

  • 将removeAtIndex()的结果作为第一个参数传递给insert()调用,而不是将其存储在中间常量中(后者由swap2()完成)
  • 操作类成员变量而不是函数局部变量(后者由swap3()完成)。

我的问题:为什么swap1()表现不同?

2 个答案:

答案 0 :(得分:2)

在同一声明中有两个array的变换器。这通常是一个坏主意,导致未定义的行为。这与你不想做的原因相同:

a = a++ + a++;

从人的角度来看,很明显您首先删除了一个项目,然后将其添加回已删除的数组中。

从编译器的角度来看,它必须做3件事来修改数组:1)读取原始数组的内容,2)修改内容,3)将它们写回。编译器必须在语句中执行两次:

array.insert(array.removeAtIndex(0), atIndex:1)

您希望编译器执行此操作:

1) temp1 = array
2) temp1.removeItem
3) array = temp1
4) temp2 = array
5) temp2.addItem
6) array = temp2

但确实如此:

1) temp1 = array
2) temp2 = array
3) temp2.removeItem
4) array = temp2
5) temp1.addItem
6) array = temp1

编译器的操作顺序是允许的,这就是为什么你不应该在同一个语句中放置两个mutator。

答案 1 :(得分:0)

这似乎是如何在Swift中处理数组的副作用。我相信Apple仍在试图找出在Swift中处理可变/不可变数组的最佳方法,而且这种行为很可能会改变(并且已经在beta版中发生了变化。

这是一篇很好的文章(或文章流,详细介绍了迄今为止的一些行为和变化):

http://blog.human-friendly.com/swift-arrays-the-bugs-the-bad-and-the-ugly-incomplete