ArrayLiteralConvertible: обычный протокол?

Пытаюсь понять и оценить, как работает ArrayLiteralConvertible...

struct Struct<T>: ArrayLiteralConvertible {

    init(arrayLiteral elements: T...) {
        for element in elements {
            print(element)
        }
    }
}

let str: Struct<Int> = [1,2,3]

Выход:

1
2
3

Теперь я пытаюсь сделать то же самое, но на этот раз со своей собственной версией ArrayLiteralConvertible:

protocol MyALC {
    typealias Element
    init(arrLit elements: Self.Element...)
}

struct NewStruct<T>: MyALC {

    init(arrLit elements: T...) {
        for element in elements {
            print(element)
        }
    }
}

let newStr: NewStruct<Int> = [1,2,3]

Однако это не работает!

error: cannot convert value of type '[Int]' to specified type 'NewStruct'
let newStr: NewStruct = [1,2,3]

Я делаю что-то не так или для ArrayLiteralConvertible существует специальная обработка?


person adev    schedule 10.09.2015    source источник


Ответы (1)


Как правило, литералы являются чисто артефактом времени компиляции. Их можно использовать для создания объекта, инициализированного из этого литерала, но как только фаза компиляции закончится, никто не узнает, что что-то было литералом.

Это говорит о том, что любая поддержка нижеприведенных протоколов должна быть встроена в сам компилятор:

  • ArrayLiteralConvertible
  • BooleanLiteralConvertible
  • DictionaryLiteralConvertible
  • ExtendedGraphemeClusterLiteralConvertible
  • FloatLiteralConvertible
  • NilLiteralConvertible
  • IntegerLiteralConvertible
  • StringLiteralConvertible
  • StringInterpolationConvertible
  • UnicodeScalarLiteralConvertible

Компилятор не будет принимать ваш собственный протокол в качестве замены любого из вышеперечисленных.

person Sergey Kalinichenko    schedule 10.09.2015
comment
Спасибо за ответ dasblinkenlight. Однако в вашем ответе есть несколько аспектов, некоторые из которых я хотел бы обсудить: 1. Понял и согласился с вашими замечаниями относительно литералов в целом. 2. Также понятно, что как литералы нуждаются в поддержке компилятора, так и эти литералы протоколов будут нуждаться в том же. 3. Что сложно переварить (насчет Swift — не ваш ответ), так это то, что Swift будет специализированно относиться к определенным протоколам. Это кажется нечестным с точки зрения языка. Гораздо лучше было бы открыто классифицировать их с помощью специальной конструкции. - person adev; 10.09.2015
comment
@adev Подход, когда поддержка компилятора добавляется для определенных классов стандартной библиотеки, в наши дни является обычным явлением. Я знаю ситуации, когда это происходит в Java, C#, Objective-C и Swift. Кстати, есть много других мест, где Swift это делает: например, компилятор имеет встроенную поддержку для Optional<T>, а также для вещей, которые вы можете поместить внутрь конструкции if let something = ... {}. - person Sergey Kalinichenko; 10.09.2015
comment
Спасибо dasblinkenlight. Я думаю, нужно просто знать такие вещи, когда они случаются. Особенно по классам и т. д. - person adev; 10.09.2015