Swift 5.1 中的递归枚举问题

Problem with recursive enums in Swift 5.1

我正在使用 Swift 文档学习 Swift 5.1 中的递归枚举。

这是一个代码。

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)

    func evaluate(_ expression: ArithmeticExpression) -> Int {
        switch expression {
        case let .number(value):
            return value
        case let .addition(left, right):
            return evaluate(left) + evaluate(right)
        case let .multiplication(left, right):
            return evaluate(left) * evaluate(right)
        }
    }
}

let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))

print(ArithmeticExpression.evaluate(product))

我认为最后一行代码出了问题。

这是什么意思?

evaluate(_:)ArithmeticExpression 实例函数 ,即您必须在 实例上调用它 ArithmeticExpression 的(那个实例是 self 所指的)。 evaluate(_:) 的类型是 (ArithmeticExpression) -> Int.

Swift 允许您调用类型的实例函数。你得到的是一个未绑定的实例函数。也就是说,一个函数还没有值绑定为它的 self 值。当你 运行 ArithmeticExpression.evaluate 独自一人时,这就是你正在做的事情。您返回的未绑定实例函数的类型为:

(ArithmeticExpression) -> (ArithmetricExpression) -> Int
// ^---  the "self"        ^--- the "expression" param ^--- the final return value.

通过调用它并提供 product 作为参数 (ArithmeticExpression.evaluate(product)),您得到的是 (ArithmeticExpression) -> Int 类型的函数。此函数是一个 绑定实例函数 ,即 self 现在已绑定(它现在具有 product 的值),但它正在等待再次调用,以另一个 ArithmeticExpression 作为参数。

有两种方法可以解决这个问题来达到你想要的效果:

  1. 要么将其设为静态函数。静态函数不是在实例上调用的,而是直接在类型上调用的,正如您尝试做的那样:

    indirect enum ArithmeticExpression {
        case number(Int)
        case addition(ArithmeticExpression, ArithmeticExpression)
        case multiplication(ArithmeticExpression, ArithmeticExpression)
    
        // Make it static here
        static func evaluate(_ expression: ArithmeticExpression) -> Int {
            switch expression {
            case let .number(value):
                return value
            case let .addition(left, right):
                return evaluate(left) + evaluate(right)
            case let .multiplication(left, right):
                return evaluate(left) * evaluate(right)
            }
        }
    }
    
    let five = ArithmeticExpression.number(5)
    let four = ArithmeticExpression.number(4)
    let sum = ArithmeticExpression.addition(five, four)
    let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
    
    print(ArithmeticExpression.evaluate(product))
    
  2. evaluate 保留为实例函数,但直接在您要计算的实例上调用它,而不是在类型上调用。由于 self 是您感兴趣的表达式,因此您不再需要 expression 参数:

    indirect enum ArithmeticExpression {
        case number(Int)
        case addition(ArithmeticExpression, ArithmeticExpression)
        case multiplication(ArithmeticExpression, ArithmeticExpression)
    
        func evaluate() -> Int {
            switch self {
            case let .number(value):
                return value
            case let .addition(left, right):
                return left.evaluate() + right.evaluate()
            case let .multiplication(left, right):
                return left.evaluate() * right.evaluate()
            }
        }
    }
    
    let five = ArithmeticExpression.number(5)
    let four = ArithmeticExpression.number(4)
    let sum = ArithmeticExpression.addition(five, four)
    let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
    
    print(product.evaluate())
    

    我想说这可能是更 "idiomatic" 的版本。