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
в качестве аргумента .
Есть два способа решить эту проблему, чтобы добиться того, что вы хотите:
Либо сделать эту функцию обычной c. Функция stati c не вызывается для экземпляра, она вызывается непосредственно для типа, как вы пытались сделать:
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))
Сохранить 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())
Я бы сказал, что это, вероятно, более "идиоматическая c" версия.