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.comUrbana, IL(217) 721-9981
enum Binds {
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 ~=(pattern: Binds, value: T) -> Bool {
switch pattern {
case .bind(let bind):
return bind(value)
case .constant(value):
return true
default:
return false
}
}
/* a + b î */
struct Complex {
let a: A
let b: B
init(_ a: A, _ b: B) {
self.a = a
self.b = b
}
}
let î = Complex(0, 1)
func ~=(pattern: Complex, value: Complex) -> Bool {
return pattern.a ~= value.a && pattern.b ~= value.b
}
func +(l: Complex,
r: Complex)
-> Complex {
return Complex(l.a + r.a, r.a + r.b)
}
func *(l: Complex,
r: Complex)
-> Complex {
return Complex(l.a * r.a - l.b * r.b, l.a * r.b + l.b * r.a)
}
func +(l: Binds, r: Complex)
-> Complex {
return Complex(l + r.a, r.b)
}
func +(l: Double, r: Complex)
-> Complex {
return Complex(l + r.a, r.b)
}
func *(l: Double, r: Complex)
-> Complex {
return Complex(l * r.a, l * r.b)
}
func +(l: Double, r: Complex)
-> Complex {
return Complex(l + r.a, r.b)
}
func +(l: Float, r: Complex)
-> Complex {
return Complex(Double(l) + r.a, r.b)
}
func *(l: Complex, r: Binds)
-> Complex {
return Complex(l.a * r, l.b * r)
}
func *(l: Binds, r: Binds) -> Binds {
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