To jde jednoduše v C++ (předefinováním operátorů, jak už tu zaznělo), nicméně pro iOS existuje elegantnější řešení ve Swiftu. Omezíme-li se na sčítání a Double, jde to takto:
protocol Expression {
func evaluate(vars:[String:Constant]) throws -> Constant
var string:String { get }
}
extension Expression where Self:CustomStringConvertible {
var string:String { return description }
}
protocol Constant : Expression {}
extension Constant {
func evaluate(vars:[String:Constant]) throws -> Constant { return self }
}
extension Double : Expression, Constant {}
enum ExpressionError : ErrorType {
case FreeVariable
case UnhandledType
}
struct Variable : Expression {
let name:String
init(name:String) { self.name = name }
func evaluate(vars:[String:Constant]) throws -> Constant {
if let value = vars[name] { return value }
else { throw ExpressionError.FreeVariable }
}
var string:String { return "$" + name }
}
struct Var {
static var x:Variable { return Variable(name: "x") }
}
struct PlusExpression : Expression {
let lhs:Expression
let rhs:Expression
init(lhs:Expression, rhs:Expression) { self.lhs = lhs; self.rhs = rhs }
func evaluate(vars:[String:Constant]) throws -> Constant {
return try lhs.evaluate(vars) + rhs.evaluate(vars)
}
var string:String { return lhs.string + " + " + rhs.string }
}
func +(lhs:Expression, rhs:Expression) -> Expression {
return PlusExpression(lhs: lhs, rhs: rhs)
}
func +(lhs:Constant, rhs:Constant) throws -> Constant {
if let x = lhs as? Double {
if let y = rhs as? Double {
return x + y
}
}
throw ExpressionError.UnhandledType
}
let expr = Var.x + 5
print(expr.string)
print(try expr.evaluate([ "x": 3 ]))
Triviálně to jde samozřejmě rozšířit na řetězce, komplexní čísla, matice atd.