有没有一种 Swift-er 方法可以将枚举案例称为可以通过类型检查的'type'?



我正在尝试开发一个解析器,该解析器使用表示令牌的Swift枚举。我希望能够验证令牌是某种类型的令牌(例如,在这种情况下是枚举的某种情况(。看看Swift文档,在没有额外枚举的情况下实现这一点的方法对我来说并不明显,我也不乐观。以下内容是否接近于一个更简洁的纯Swift语言级解决方案?

enum SymbolTokenType {
case river, lake, mountain, meadow, valley, openParen, closeParen, logicalAnd, logicalOr, logicalNot
}
enum SymbolToken {
case river              (key: RiverKey?)
case lake               (key: LakeKey?)
case mountain           (key: MountainKey?)
case meadow             (key: MeadowKey?)
case valley             (key: ValleyKey?)
case openParen
case closeParen
case logicalAnd
case logicalOr
case logicalNot

func validateTokenType(validTypes: [SymbolTokenType] ) -> Bool {
switch(self) {
case .river:
return validTypes.contains(.river)
case .lake:
return validTypes.contains(.lake)
case .mountain:
return validTypes.contains(.mountain)
case .meadow:
return validTypes.contains(.meadow)
case .valley:
return validTypes.contains(.valley)
case .openParen:
return validTypes.contains(.openParen)
case .closeParen:
return validTypes.contains(.closeParen)
case .logicalAnd:
return validTypes.contains(.logicalAnd)
case .logicalOr:
return validTypes.contains(.logicalOr)
case .logicalNot:
return validTypes.contains(.logicalNot)
}
}
}

我想这样做:

enum Token {
case token1
case token2
case token3

func isValid(from container: [Token]) -> Bool {
container.contains(self)
}
}
let validTokens: [Token] = [.token1, .token2]
let testedToken2 = Token.token2
let testedToken3 = Token.token3
testedToken2.isValid(from: validTokens) // True
testedToken3.isValid(from: validTokens) // False

--UPD-

如果enum有关联的值,我会这样做:

enum Token {
case token1    (key: String?)
case token2    (key: String?)
case token3    (key: String?)

func isValid(from container: [Token]) -> Bool {
container.contains(self)
}
}
extension Token: RawRepresentable, Equatable {
typealias RawValue = Int

init?(rawValue: Int) {
switch rawValue {
case 1:  self = .token1(key: nil)
case 2:  self = .token2(key: nil)
case 3:  self = .token3(key: nil)

default: return nil
}
}

var rawValue: Int {
switch self {
case .token1: return 1
case .token2: return 2
case .token3: return 3
}
}

// Equatable
static func == (lhs: Token, rhs: Token) -> Bool {
lhs.rawValue == rhs.rawValue
}
}

结果:

let validTokens: [Token] = [.token1(key: nil), .token2(key: nil)]
let testedToken2 = Token.token2(key: "Second token")
let testedToken3 = Token.token3(key: "Third token")
testedToken2.isValid(from: validTokens) // True
testedToken3.isValid(from: validTokens) // False

您绝对不需要两个枚举。您只需要以不同的方式处理具有相关值的案例。

protocol SimilarComparable: Equatable {
func isSimilar(to other: Self) -> Bool
func isSimilar(toAny others: [Self]) -> Bool
}
extension SimilarComparable {
func isSimilar(toAny others: [Self]) -> Bool {
let result = others.first(where: { $0.isSimilar(to: self) }) != nil
print("Finding similarity to (self) in (others) == (result)")
return result
}
}
enum SymbolToken: SimilarComparable {
case river              (key: String?)
case lake               (key: String?)
case mountain           (key: String?)
case meadow             (key: String?)
case valley             (key: String?)
case openParen
case closeParen
case logicalAnd
case logicalOr
case logicalNot
func isSimilar(to other: SymbolToken) -> Bool {
let result: Bool
print("Finding similarit to (self) to (other) == ", separator: " ", terminator: "")
switch (self, other) {
case (.river, .river):
result = true
case (.lake, .lake):
result = true
case (.mountain, .mountain):
result = true
case (.meadow, .meadow):
result = true
case (.valley, .valley):
result = true
default:
result = self == other
}
print("(result)")
return result
}
}

用法如下:

_ = SymbolToken.river(key: "Hudson").isSimilar(to: .river(key: "Nile")) // true
_ = SymbolToken.lake(key: "Michigan").isSimilar(to: .lake(key: "Tahoe")) // true
_ = SymbolToken.closeParen.isSimilar(to: .closeParen) // true
_ = SymbolToken.logicalOr.isSimilar(to: .logicalOr) // true
_ = SymbolToken.logicalOr.isSimilar(to: .logicalAnd) // false
let tokens: [SymbolToken] = [
.river(key: "Hudson"),
.lake(key: "Tahoe"),
.closeParen,
.logicalOr,
]
_ = SymbolToken.logicalOr.isSimilar(toAny: tokens) // true
_ = SymbolToken.lake(key: "Michigan").isSimilar(toAny: tokens) // true

最新更新