如何在Swift中创建通用转换管道

4sup72z8  于 2023-02-03  发布在  Swift
关注(0)|答案(1)|浏览(197)

我尝试在swift中创建一个基本的转换管道。

import Foundation

protocol Transformation {
    associatedtype Target
    func transform(_ input: Target) -> Target
}

struct LowercaseTransformation: Transformation {
    func transform(_ input: String) -> String {
        return input.lowercased()
    }
}

struct ReverseTransformation: Transformation {
    func transform(_ input: String) -> String {
        return String(input.reversed())
    }
}

struct Pipeline<T> where T: Transformation {
    let transformations: [T]

    func run(_ input: T.Target) -> T.Target {
      var output = input
      transformations.forEach { output = $0.transform(output) }
      return output
    }
}

let pipeline = Pipeline(transformations: [LowercaseTransformation(), ReverseTransformation()]) // Type of expression is ambiguous without more context
let input: String = "Hello World"
let output = pipeline.run(input)
print(output)

我的问题与泛型的使用有关,但我一直不能想出如何在保持转换协议和管道结构可重用的同时绕过它...
刚刚又试了一次。。这适用于阵列中的一个变压器,甚至是同一个变压器的多个示例,但只要阵列包含不同的变压器,它就会中断。。

protocol Transform {
    associatedtype Target
    func transform(input: Target) -> Target
}

struct Transformer: Transform {
  func transform(input: String) -> String {
    input+"_Transformed"
  }
}

struct AnotherTransformer: Transform {
  func transform(input: String) -> String {
    input+"_Morphed"
  }
}

struct TransformPipeline<Target, Transformer: Transform> where Transformer.Target == Target {
  private let transforms: [Transformer]

  init(transforms: [Transformer]) {
        self.transforms = transforms
    }

    func run(input: Target) -> Target {
        var output = input
        for transform in transforms {
          output = transform.transform(input: output)
        }
        return output
    }
}

let transformations = [Transformer()]
let pipeline = TransformPipeline(transforms: transformations)

print(pipeline.run(input: "input"))
yrwegjxp

yrwegjxp1#

一个非常简化的版本是只使用Pipeline结构,并让它保存一个函数数组

struct Pipeline<Target> {
    typealias Transformer = (Target) -> Target
    let transformations: [Transformer]

    func transform(_ input: Target) -> Target {
        var output = input
        for transformation in transformations {
            output = transformation(output)
        }
        return output
    }
}

然后使用

let pipeline = Pipeline<String>(transformations: [{ $0.uppercased() }, { String($0.reversed()) }])

为了更好地使用Pipeline,我们可以为函数声明一些静态属性

extension Pipeline where Target == String {
    static let uppercased: Transformer = {
        { $0.uppercased() }
    }()

    static let reversed: Transformer = {
        { String($0.reversed()) }
    }()
}

let pipeline = Pipeline<String>(transformations: [ Pipeline.uppercased, Pipeline.reversed])

相关问题