Swift: recursive value type

I have a structure in which I want to have a global variable of type Struct ?. This example is essentially a shorter version of the structure that I actually create.

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) } } } 

However, it throws an error:

 Recursive value type 'SplitString' is not allowed 

Is there any way around this? Any help would be great. Thanks:)

Edit: In case this is relevant, I am programming on iOS, not OSX.

Edit: If I have:

 var split = SplitString("first/second/third") 

I expect split to be:

 {preSlash = "first", postSlash = {preSlash = "second", postSlash = {preSlash = "third", postSlash = nil}}} 
+6
source share
2 answers

TL DR:

What you are trying to achieve is easily accomplished with split:

 for s in split("first/second/third", { c in c == "/" } ) { println("\(s)") } 

Discussion

It looks like you are trying to write a linked list of value types. The problem is that Swift combines the concepts of copy semantics with value / reference access. (unlike C ++, which allows you to create the same object on the stack or heap). The solution seems to be wrapping it in a aka class reference container.

 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) } } 

Please note that this code compiles as a proof of concept, but I have not delved into your algorithm or tested it.

Edit:

In response to your changes above, this code will execute your code above and give the splits you need:

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

Obviously, turtles completely omitted does not make sense in the discussion above, so you need to break the loop, as was the case with the class containing your structure.

Please note that I tried to answer the question that you posted, not what you have. The solution to the problem that you have is to use SequenceOf and GeneratorOf to create a generator that completes the sequence that iterates through the slashes and returns the substrings between them. This is really done for you through the split function:

 for s in split("first/second/third", { c in c == "/" } ) { println("\(s)") } 
+6
source

I assume this is because the optional behaves like a value type. So you have a value type value type. Type of value.

To make a layout for a value type, you need to know the size of the things involved.

So you have (simplified):

 sizeof(SplitString) = sizeof(String) + sizeof(SplitString?) 

with

 sizeof(SplitString?) > sizeof(SplitString) 

since you need to preserve the fact that the value is there or not (and, no, the sizeof zero-size template (SplitString) is not a valid representation for it, as it would be for the class type - why? Int? = 0)

So now you have

 sizeof(SplitString?) > sizeof(String) + sizeof(SplitString?) 

but all the quantities involved are definitely> 0. Rather absurd, right?

+8
source

Source: https://habr.com/ru/post/976687/


All Articles