Я могу создать итератор для создания префиксов:
extension Array where Element == Int {
func prefixesInt() -> AnyIterator<[Element]> {
var length = 0
return AnyIterator {
guard length < self.count else { return nil }
length += 1
return Array(self.prefix(length))
}
}
}
for prefix in [1,10,5].prefixesInt() {
print(prefix) // Prints: [1] then [1, 10] then [1, 10, 5]
}
Теперь я хочу добиться того же с другими типами:
1) Кодирование типов в Ints
2) Использование той же префиксной функции
3) Возвращение к исходному типу
[Я знаю, что могут быть другие способы добиться этого, но я хочу следовать этой линии по разным причинам, а также хочу понять больше.]
Итак, мне нужно:
extension Array where Element: Equatable {
func encode() -> [Int] {
return map { self.firstIndex(of: $0)! }
}
}
print(["A", "B", "A", "C"].encode()) // Prints: [0, 1, 0, 3]
extension Array where Element == Int {
func decode<Output>(_ original: [Output]) -> [Output] {
return map { original[$0] }
}
}
print([2,3,0].decode(["P", "Q", "R", "S"])) // Prints: ["R", "S", "P"]
Теперь я могу делать то, что хочу:
extension Array where Element: Equatable {
func prefixes() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
return encode().prefixesInt().lazy.map { $0.decode(self) }
}
}
for prefix in ["H","A","T"].prefixes() {
print(prefix)
}
Теперь я хочу пойти еще дальше, сделав преобразование (в данном случае префиксы) параметром, и моя попытка такова:
extension Array where Element: Equatable {
func encodeTransformDecode(transform: ([Int]) -> AnyIterator<[Int]> ) -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
return transform(encode()).lazy.map { $0.decode(self) }
}
}
который компилируется нормально, но когда я пытаюсь:
extension Array where Element: Equatable {
func prefixes2() -> LazyMapSequence<AnyIterator<[Element]>, [Element]> {
return encodeTransformDecode(transform: prefixesInt) //ERROR: 'Array<Element>' is not convertible to 'Array<Int>'
}
}
for prefix in ["A","B","C"].prefixes2() {
print(prefix)
}
Затем я получаю указанную ошибку
Я застрял. Любая помощь приветствуется.
Весь код:
print("========== prefixesInt")
extension Array where Element == Int {
func prefixesInt() -> AnyIterator<[Element]> {
var length = 0
return AnyIterator {
guard length < self.count else { return nil }
length += 1
return Array(self.prefix(length))
}
}
}
for prefix in [1,10,5].prefixesInt() {
print(prefix) // Prints: [1] then [1, 10] then [1, 10, 5]
}
print("============ encode")
extension Array where Element: Equatable {
func encode() -> [Int] {
return map { self.firstIndex(of: $0)! }
}
}
print(["A", "B", "A", "C"].encode()) // Prints: [0, 1, 0, 3]
print("============ decode")
extension Array where Element == Int {
func decode<Output>(_ original: [Output]) -> [Output] {
return map { original[$0] }
}
}
print([2,3,0].decode(["P", "Q", "R", "S"])) // Prints: ["R", "S", "P"]
print("============ prefixes")
extension Array where Element: Equatable {
func prefixes() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
return encode().prefixesInt().lazy.map { $0.decode(self) }
}
}
for prefix in ["H","A","T"].prefixes() {
print(prefix)
}
extension Array where Element: Equatable {
func encodeTransformDecode(transform: ([Int]) -> AnyIterator<[Int]> ) -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
return transform(encode()).lazy.map { $0.decode(self) }
}
}
print("============ prefixes2")
extension Array where Element: Equatable {
func prefixes2() -> LazyMapSequence<AnyIterator<[Element]>, [Element]> {
return encodeTransformDecode(transform: prefixesInt)
}
}
for prefix in ["A","B","C"].prefixes2() {
print(prefix)
}
Но подпись encodeTransformDecode спрашивает, имеет ли преобразование тип: ([Int]) -> AnyIterator <[Int]>, так что не ясно в сообщении?
Вы не можете вызвать prefixesInt из массива, в котором единственное ограничение на элемент должно быть равнозначным. Плюс подпись prefixesInt не ([Int]) -> AnyIterator<[Int]>
Какую версию Xcode / Swift вы используете? Комментирование вашей ошибки в конце и запуск дает результат с ожидаемым плюсом SWIFT RUNTIME BUG: unable to demangle type of field '_transform'. mangled type name is 'q_7ElementSTQzc' в игровой площадке Xcode 10.0 / Swift 4.2
Привет @CRD, версия - Xcode 10.1 (10B61)
Спасибо @ Carpsen90 за помощь в этом. Ваш вопрос заставляет меня понять, что я не понимаю тип prefixesInt. Я предположил, что, поскольку это метод на [Int] и возвращает AnyIterator<[Int]>, его типом будет ([Int]) -> AnyIterator<[Int]>, но я полагаю, что я не прав?
Его тип - () -> AnyIterator<[Int]>.
Я думаю, вам не хватает одной вещи, так это то, что в encodeTransformDecode(transform: prefixesInt) есть ссылка скрытыйself, поскольку prefixesInt является методом экземпляра - и в этом случае этот self не относится к типу [Int]. Это дает вам две проблемы: неправильный тип, и даже если это был правильный тип, вы неявно связали self. Если вы определите метод staticprefixesInt, который принимает [Int] и просто вызывает версию экземпляра в своем аргументе, передайте его в encodeTransformDecode, и вы продвинетесь дальше. (У меня ваш код "работает" в 10.0, но он извергает ОШИБКИ РАБОТЫ, поэтому публиковать не буду!)
Спасибо @CRD. Я задавался вопросом, но не очень ясно об этом, поэтому ваш комментарий подтолкнул меня к исследованию ... Я очень хотел не идти по статическому маршруту - это делает другие части кода менее элегантными. У меня были довольно смутные воспоминания о некоторых методах каррирования из превосходного "obj Functional Swift". Я поискал его, и это помогло мне уточнить, что тип prefixesInt на самом деле: (Array<Int>) -> () -> AnyIterator<[Int]>. Осознание этого дает мне решение. Я отправлю свои выводы в качестве ответа.





С помощью полезных советов от @ Carpsen90 и @CRD (спасибо обоим!) И некоторого погружения в отличную книгу "obj Functional Swift" (без личного контакта) я нашел решение.
Тип метода экземпляра отличается от статического метода, как показано:
extension Int {
static func doubleStatic(_ x: Int) -> Int { return x * 2 }
func doubleInstance() -> Int { return self * 2 }
}
print( type(of: Int.doubleStatic) ) // Prints: (Int) -> Int
print( type(of: Int.doubleInstance) ) // Prints: (Int) -> () -> Int
В вопросе тип prefixesInt на самом деле: (Array<Int>) -> () -> AnyIterator<[Int]>.
Имея это в виду, мы можем переписать encodeTransformDecode следующим образом:
extension Array where Element: Equatable {
func encodeTransformDecode(transform: (Array<Int>) -> () -> AnyIterator<[Int]> ) -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
return transform(encode())().lazy.map { $0.decode(self) }
}
}
Во-вторых, нам нужно сообщить компилятору немного больше о типе prefixesInt, когда мы будем использовать его в prefixes2, поэтому:
extension Array where Element: Equatable {
func prefixes2() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
return encodeTransformDecode(transform: Array<Int>.prefixesInt)
}
}
а теперь по мере необходимости:
for prefix in ["A","B","C"].prefixes2() {
print(prefix)
}
дает нам:
["A"]
["A", "B"]
["A", "B", "C"]
и теперь мы можем очень легко расширить с помощью другой функции очень кратко:
extension Array where Element == Int {
func suffixesInt() -> AnyIterator<[Element]> {
var length = 0
return AnyIterator {
guard length < self.count else { return nil }
length += 1
return Array(self.suffix(length))
}
}
}
extension Array where Element: Equatable {
func suffixes2() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
return encodeTransformDecode(transform: Array<Int>.suffixesInt)
}
}
for suffix in ["A","B","C"].suffixes2() {
print(suffix)
}
Возможно, фраза: transform(encode())().lazy.map { $0.decode(self) } загадочна и может быть лучше: let encoded = encode()let transformFunction = transform(encoded)let transformIterator = transformFunction()let lazyTransformIterator = transformIterator.lazyreturn lazyTransformIterator.map { $0.decode(self) }
Как указано в моем комментарии, и вы исследовали в своем собственном ответе, основная проблема в вашем коде заключается в том, что у вас неправильный тип prefixesInt. Метод экземпляра имеет тип формы:
(<object type>) -> (<argument types>) -> <return type>
значение, переданное для <object type>, - это то, что связано с self в функции. Итак, тип prefixesInt:
([Int]) -> () -> AnyIterator<[Int]>
Чтобы исправить ваш код, вам нужно только изменить prefixes2:
func prefixes2() -> LazyMapSequence<AnyIterator<[Int]>, [Element]>
{
return encodeTransformDecode(transform: { $0.prefixesInt() } )
}
Тип был изменен и теперь включает AnyIterator<[Int]>, а не AnyIterator<[Element]>, и передается закрытие { $0.prefixesInt() }, а не просто prefixesInt (первый принимает массив в качестве аргумента, а компилятор передает последний, что является сокращением для self.prefixesInt, в качестве закрытия с текущим значением Предварительно связанный self - этот self, являющийся Array<Equatable>, был вызван prefixes2).
HTH
Чтобы увидеть связь с созданным вами кодом, учтите, что:
<value>.method(<args>)
это просто сокращение для:
<type of value>.method(<value>)(<args>)
Что в данном случае означает, что:
$0.prefixesInt()
это сокращение для:
Array<Int>.prefixesInt($0)()
это то, что вы создали, но распространяли между prefixes() (Array<Int>.prefixesInt) и encodeTransformDecode (transform(encode())()). При использовании сокращения и закрытии никаких изменений в encodeTransformDecode не требуется.
Спасибо, CRD. Ваш ответ действительно проясняет мое понимание. Очень признателен.
prefixesIntопределяется только наArray where Element == Int, а не в массивах вообще