Sometimes I wish for custom *binding* patterns in Swift. Is something like this already in the works? Anyone else wishing for this?
I have attached some code where I fake it, but these examples show what I'm really after: /* Match complex numbers, let expressions with type qualification: */ for elt in [1.0 + î, 2.0 + 3.0 * î, 4.0 + 5.0 * î, 6.0 * î] { switch elt { case î * (let d: Double): print("matched î * \(d)") case 1 + î * (let a: Double): print("matched 1 + î * \(a)") case (let b: Double) + î * (let c: Double): print("matched \(b) + î * \(c)") default: print("no match") } } /* Match complex numbers, let expressions with types inferred: */ for elt in [1.0 + î, 2.0 + 3.0 * î, 4.0 + 5.0 * î, 6.0 * î] { switch elt { case î * (let d): print("matched î * \(d)") case 1 + î * (let a): print("matched 1 + î * \(a)") case (let b) + î * (let c): print("matched \(b) + î * \(c)") default: print("no match") } } /* Match strings, assigning substrings to numeric types a la scanf(3): */ if case "\(let a: Double) + \(let b: Double) î" = "1 + 2 î" { print("matched \(a) + \(b) î") } /* Approximately match strings; `fuzz` is an "edit distance" between * the pattern and the match. */ if case ApproximateMatch("\(let a: Double) + \(let b: Double) î", let fuzz) = "1 + 2 * î", fuzz < 5 { print("matched \(a) + \(b) î with fuzz \(d)") } /* Simplify an algebraic expression: n1 / d + n2 / d -> (n1 + n2) / d. * * Original source: */ if case .sum(.quotient(let ln, let ld), .quotient(let rn, let rd)) = expr, ld == rd { return evaluate(.quotient(.sum(ln, rn), ld), env) } /* => with operator overloading (no custom binding patterns) becomes: */ if case .sum(.quotient(let ln, let ld), .quotient(let rn, let rd)) = expr, ld == rd { return evaluate((ln + rn) / ld, env) } /* => with custom binding patterns and operator overloading becomes: */ if case (let ln: Expr) / (let ld: Expr) + (let rn: Expr) / (let rd: Expr) = expr, ld == rd { return evaluate((ln + rn) / ld, env) } /* => with type inference becomes: */ if case (let ln) / (let ld) + (let rn) / (let rd) = expr, ld == rd { return evaluate((ln + rn) / ld, env) } Dave -- David Young dyo...@pobox.com Urbana, IL (217) 721-9981
enum Binds<T : Equatable> { case constant(T) case bind((T) -> Bool) case matchless } extension Binds : CustomStringConvertible { var description: String { switch self { case .bind(_): return ".bind(_)" case .constant(let x): return ".constant(\(x))" case .matchless: return ".matchless" } } } func ~=<T>(pattern: Binds<T>, value: T) -> Bool { switch pattern { case .bind(let bind): return bind(value) case .constant(value): return true default: return false } }
/* a + b î */ struct Complex<A, B> { let a: A let b: B init(_ a: A, _ b: B) { self.a = a self.b = b } } let î = Complex<Double, Double>(0, 1) func ~=<V>(pattern: Complex<Binds<V>, Binds<V>>, value: Complex<V, V>) -> Bool { return pattern.a ~= value.a && pattern.b ~= value.b } func +(l: Complex<Binds<Double>, Binds<Double>>, r: Complex<Binds<Double>, Binds<Double>>) -> Complex<Binds<Double>, Binds<Double>> { return Complex(l.a + r.a, r.a + r.b) } func *(l: Complex<Binds<Double>, Binds<Double>>, r: Complex<Binds<Double>, Binds<Double>>) -> Complex<Binds<Double>, Binds<Double>> { return Complex(l.a * r.a - l.b * r.b, l.a * r.b + l.b * r.a) } func +(l: Binds<Double>, r: Complex<Binds<Double>, Binds<Double>>) -> Complex<Binds<Double>, Binds<Double>> { return Complex(l + r.a, r.b) } func +(l: Double, r: Complex<Binds<Double>, Binds<Double>>) -> Complex<Binds<Double>, Binds<Double>> { return Complex(l + r.a, r.b) } func *(l: Double, r: Complex<Double, Double>) -> Complex<Double, Double> { return Complex(l * r.a, l * r.b) } func +(l: Double, r: Complex<Double, Double>) -> Complex<Double, Double> { return Complex(l + r.a, r.b) } func +(l: Float, r: Complex<Double, Double>) -> Complex<Double, Double> { return Complex(Double(l) + r.a, r.b) } func *(l: Complex<Double, Double>, r: Binds<Double>) -> Complex<Binds<Double>, Binds<Double>> { return Complex(l.a * r, l.b * r) }
func *(l: Binds<Double>, r: Binds<Double>) -> Binds<Double> { switch (l, r) { case (.constant(let x), .constant(let y)): return .constant(x * y) case (.constant(0), _), (_, .constant(0)): return .constant(0) case (.constant(1), _): return r case (_, .constant(1)): return l default: return .matchless } } func -(l: Binds<Double>, r: Binds<Double>) -> Binds<Double> { switch (l, r) { case (.constant(let x), .constant(let y)): return .constant(x - y) case (.constant(0), .bind(let f)): return .bind({ x in return f(-x) }) case (.constant(0), _): return r case (_, .constant(0)): return l default: return .matchless } } func +(l: Binds<Double>, r: Binds<Double>) -> Binds<Double> { switch (l, r) { case (.constant(let x), .constant(let y)): return .constant(x + y) case (.constant(0), _): return r case (_, .constant(0)): return l default: return .matchless } } func *(l: Double, r: Binds<Double>) -> Binds<Double> { switch l { case 0: return .constant(0) case 1: return r default: break } switch r { case .constant(let x): return .constant(l * x) case .bind(let f): return .bind({ x in return f(x / l) }) default: return .matchless } } func +(l: Double, r: Binds<Double>) -> Binds<Double> { switch r { case .constant(let x): return .constant(l + x) case .bind(let f): return .bind({ x in return f(x - l) }) default: return .matchless } }
var a: Double = 0 var b: Double = 0 var c: Double = 0 var d: Double = 0 let leta: Binds<Double> = .bind({ x in a = x; return true }) let letb: Binds<Double> = .bind({ x in b = x; return true }) let letc: Binds<Double> = .bind({ x in c = x; return true }) let letd: Binds<Double> = .bind({ x in d = x; return true }) for elt in [1.0 + î, 2.0 + 3.0 * î, 4.0 + 5.0 * î, 6.0 * î] { switch elt { case î * letd: print("matched î * \(d)") case 1 + î * leta: print("matched 1 + î * \(a)") case letb + î * letc: print("matched \(b) + î * \(c)") default: print("no match") } } if case 1 + î * leta = 1.0 + î { print("match!") }
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users