Swift:递归值类型

lia*_*923 6 value-type ios swift

我有一个结构,我想要一个结构类型的全局变量?这个例子本质上是我实际创建的结构的简化版本.

struct SplitString { //splits a string into parts before and after the first "/"

    var preSlash: String = String()
    var postSlash: SplitString? = nil

    init(_ str: String) {
        var arr = Array(str)
        var x = 0
        for ; x < arr.count && arr[x] != "/"; x++ { preSlash.append(arr[x]) }
        if x + 1 < arr.count { //if there is a slash
            var postSlashStr = String()
            for x++; x < arr.count; x++ {
                postSlashStr.append(arr[x])
            }
            postSlash = SplitString(postSlashStr)
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

但是,它会抛出错误:

Recursive value type 'SplitString' is not allowed
Run Code Online (Sandbox Code Playgroud)

有没有办法解决这个问题?任何帮助都会很棒.谢谢 :)

编辑:如果它是相关的,我在iOS上编程,而不是OSX编程.

编辑:如果我有:

var split = SplitString("first/second/third")
Run Code Online (Sandbox Code Playgroud)

我希望分裂为:

{preSlash = "first", postSlash = {preSlash = "second", postSlash = {preSlash = "third",
postSlash = nil}}}
Run Code Online (Sandbox Code Playgroud)

Enr*_*ata 8

我想这是因为Optional的行为类似于值类型.所以你拥有的是值类型的值类型.值类型.

要为值类型进行布局,您需要知道所涉及事物的大小.

所以你有(简化):

sizeof(SplitString) = sizeof(String) + sizeof(SplitString?)
Run Code Online (Sandbox Code Playgroud)

sizeof(SplitString?) > sizeof(SplitString)
Run Code Online (Sandbox Code Playgroud)

因为你需要存储值存在或不存在的事实(并且,不,sizeof(SplitString)零的模式不是一个有效的表示形式,因为它将是一个类类型 - 为什么?想象Int?= 0)

那么,现在你有了

sizeof(SplitString?) > sizeof(String) + sizeof(SplitString?)
Run Code Online (Sandbox Code Playgroud)

但所涉及的所有数量肯定都是0.而不是荒谬,对吧?


Chr*_*ver 6

TL; DR:

使用split可以轻松完成您要实现的目标:

for s in split("first/second/third", { c in c == "/" } ) {
    println("\(s)")
}
Run Code Online (Sandbox Code Playgroud)

讨论:

您似乎正在尝试编写值类型的链接列表.问题是Swift将复制语义的概念与值/引用访问相结合.(与C++不同,它允许您在堆栈或堆上创建相同的对象).解决方案似乎是将它包装在一个引用容器(即class)中.

class SplitString { //splits a string into parts before and after the first "/"

    var preSlash: String = String()
    var postSlash: Wrapped? = nil

    init(_ str: String) {
        var arr = Array(str)
        var x = 0
        for ; x < arr.count && arr[x] != "/"; x++ { preSlash.append(arr[x]) }
        if x + 1 < arr.count { //if there is a slash
            var postSlashStr = String()
            for x++; x < arr.count; x++ {
                postSlashStr.append(arr[x])
            }
            postSlash = Wrapped(postSlashStr)
        }
    }

}

class Wrapped {
    var split:SplitString

    init(var _ str:String) {
        split = SplitString(str)
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,此代码编译为概念证明,但我没有深入研究您的算法或测试它.

编辑:

为了回应您的上述编辑,此代码将在上面运行您的代码并生成您想要的拆分:

for (var s:SplitString? = split; s != nil; s = s?.postSlash?.split) {
    println("\(s!.preSlash)")
}
Run Code Online (Sandbox Code Playgroud)

根据上面的讨论,显然让乌龟一直都没有意义,所以你需要打破循环,就像包含你的结构的类的情况一样.

请注意,我一直在尝试回答您发布的问题,而不是您遇到的问题.解决问题的方法是使用SequenceOf和GeneratorOf创建一个序列包装的生成器,它迭代斜杠并返回它们之间的子串.这实际上是通过split函数为您完成的:

for s in split("first/second/third", { c in c == "/" } ) {
    println("\(s)")
}
Run Code Online (Sandbox Code Playgroud)

  • 你不能继续做同样的事情并期望得到不同的结果.你能用测试用例和预期结果更新你的问题吗? (2认同)