AttributedString is ExpressibleByStringLiteral so can intermix with String with ‘+’, but why .append(:) cannot take a String

AttributedString’s conforms to ExpressibleByStringLiteral so I expect this all to work:

var foo: AttrtibutedString = “1000”    // works 
let bar = foo + “000”                  // works
foo.append(“000”)             // do not work

// b/c String doesn’t conform to AttributedStringProtocol

Adding this let me using String call .append() with String:

extension AttributedString {
    mutating func append(_ string: String) {
        self.append(AttributedString(string))
    }
}

But there must be reason .append() don’t take a String by design and not an oversight and I adding this can create bug?

How make this work?

foo.append(.newline)
// it does this under the hood:
foo.append(AttributedString(“\n”))

I try adding a computed value in AttributedString but do not work. And i dont know how to add this to AttributedStringProtocol.

There are two versions of "+" for AttributedString, one accepting some AttributedStringProtocol (why not any, BTW?) and another accepting AttributedString. For append there's just one version accepting some AttributedStringProtocol. Should there be a second version:

extension AttributedString {
    mutating func append(_ string: AttributedString) {
        ...
    }
}

your example with append would have worked fine.

Note, the "000" is getting converted to AttributedString as it is ExpressibleByStringLiteral; the code won't work with actual strings:

let foo: AttributedString = ...
let s = "000"
let bar = foo + s // error

I thinknif it’s ExpressinleByStringLiteral means anybof its API that takes Self should take string literal as well to be consistent?

so, append takes AttributedStringProtocol. It would take the compiler a few assumptions to make:

  • which type to use for "000" in append? (there could be many types implementing ExpressibleByStringLiteral)
  • which of those types to prefer if more than one adheres to AttributedStringProtocol?

When there's an explicit override that takes AttributedString the task at hands is much simpler for the compiler.

1 Like

Can it not just make a Self out of a String? I’m calling .append(“blah”) so whatever AT should just be itself and no need for any compiler magic

Can an extension AttributedStringProtocol to add an append that takes a String and make a Self and call the base append?