1

I'm making a String struct (called ScalarString) from scratch that internally is an array of UInt32 Unicode scalar values (see this question for background).

For a normal Swift String I can do the following:

let myString: String = "hello"

I would like to do

let myScalarString: ScalarString = "hello"

where I overload the assignment operator to convert the "hello" String automatically to ScalarString behind the scenes. However, this SO Q&A tells me that is not possible.

I could write a method like

myScalarString.set("hello")

but that isn't as readable as the assignment operator. Is there any alternative?

myScalarString = "hello"
Community
  • 1
  • 1
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393

1 Answers1

2

To make an assignment

let myScalarString: ScalarString = "hello"

work with a string literal on the right-hand side, it suffices that you implement the StringLiteralConvertible for your type:

extension ScalarString : StringLiteralConvertible {

    init(stringLiteral value: String) {
        self.init(value)
    }

    init(extendedGraphemeClusterLiteral value: String) {
        self.init(value)
    }

    init(unicodeScalarLiteral value: String) {
        self.init(value)
    }
}

However, this works only for string literals, not for arbitrary strings, so this would not compile:

let str = "hello"
let yourScalarString: ScalarString = str

because (as you already noticed) you cannot overload the assignment operator, and you would have to use your init method explicitly:

let yourScalarString = ScalarString(str)

In the same manner, you could create a value of your type from a literal array of Unicode values

let myScalarString: ScalarString = [ 65, 66, 67 ]

by implementing the ArrayLiteralConvertible protocol:

extension ScalarString : ArrayLiteralConvertible {
    init(arrayLiteral elements: UInt32...) {
        self.init(elements)
    }

}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • So this allows one to make an assignment to a string (or array) literal (not a variable) during initialization only, correct? That is, I couldn't do something like `let myString = ScalarString()` to initialize an empty string and then later set the value with `myString = "hello"`. – Suragch Jul 22 '15 at 02:15
  • And if my statement above is correct, what is the special magic that Swift does to give this functionality to its own `String` struct? – Suragch Jul 22 '15 at 02:18
  • @Suragch: `var myString = ScalarString() ; ... ; myString = "hello"` should be possible with the above extensions. – The Swift compiler can do many things that we cannot to (e.g. automatic conversion of Int, Double, String etc to NSObject if necessary). – Martin R Jul 22 '15 at 05:28