Array <Element>не может быть преобразован в Array <Int> - PullRequest
0 голосов
/ 16 ноября 2018

Я могу создать итератор для создания префиксов:

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

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

Как указано в моем комментарии, и вы изучили в своем собственном ответе, основная проблема в вашем коде заключается в том, что у вас неправильный тип 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 pre-bound - что 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 не требуется.

0 голосов
/ 16 ноября 2018

С помощью полезных толчков от @ 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)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...