首页 > 解决方案 > 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))

屏幕

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

这意味着什么?

标签: swiftxcodeenumsconsolelldb

解决方案


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)) 提供,你得到的是一个 type 的函数(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())
    

    我会说这可能是更“惯用”的版本。


推荐阅读