'Array <element>'不能转换为'Array <int>'

时间:2018-11-16 09:56:21

标签: swift generics functional-programming lazy-sequences

我可以创建一个迭代器来创建前缀:

2018-11-16 15:08:01.523  INFO 8604 --- [ost-startStop-1] 
c.n.c.sources.URLConfigurationSource     : To enable URLs as dynamic 
configuration sources, define System property 
archaius.configurationSource.additionalUrls or make config.properties 
available on classpath.
2018-11-16 15:08:01.555  INFO 8604 --- [ost-startStop-1] 
c.netflix.config.DynamicPropertyFactory  : DynamicPropertyFactory is 
initialized with configuration sources: 
com.netflix.config.ConcurrentCompositeConfiguration@ef4443e
2018-11-16 15:08:01.977 ERROR 8604 --- [ost-startStop-1] 
o.s.b.c.embedded.tomcat.TomcatStarter    : Error starting Tomcat context. 
Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. 
Message: Error creating bean with name'org.springframework.cloud.netflix.zuul.ZuulConfiguration$ZuulFilterConfigur 
  ation': Unsatisfied dependency expressed through field 'filters'; nested 
exception is org.springframework.beans.factory.BeanCreationException: Error 
creating bean with name 'preFilter': Injection of autowired dependencies 
failed; nested exception is java.lang.IllegalArgumentException: Could not 
resolve placeholder 'zuul.prefix' in value "${zuul.prefix}"

现在我想通过以下方法实现与其他类型的相同:

1)将类型编码为整数

2)使用相同的前缀功能

3)解码回原始类型

[我知道可能还有其他方法可以实现这一目标,但是出于各种原因,我也想遵循这一思路,并且还想了解更多。]

所以我需要:

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

我现在可以做我想做的事

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

2 个答案:

答案 0 :(得分:1)

正如我的评论中所指出的,并且您已经在自己的答案中进行了研究,代码中的核心问题是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的简写形式)传递为闭包,并预先绑定当前值为selfselfArray<Equatable> prefixes2被调用)。

HTH


要查看与您生成的代码之间的联系,请考虑:

<value>.method(<args>)

只是以下各项的简写:

<type of value>.method(<value>)(<args>)

在这种情况下意味着:

$0.prefixesInt()

是以下内容的简写:

Array<Int>.prefixesInt($0)()

这是您制作的,但分布在prefixes()Array<Int>.prefixesInt)和encodeTransformDecodetransform(encode())())之间。通过使用速记并传递闭包,无需更改encodeTransformDecode

答案 1 :(得分:0)

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