Hypothetical syntax for shortening repetitive logical statements

Thoughts on this hypothetical syntax?

The motivation is to reduce verbosity in needing to repeat the left side of the comparisons.

Replace:
if a > 1 || a == 0 { ... } (reads: “if a is greater than one or a is equal to zero…“)

With:
if a (> 1 || == 0) { ... } (reads: “if a is greater than one or is equal to zero…“)

Not sure how I feel about it. I was just thinking of a possible syntax to achieve the motivation.

In my opinion, the appropriate solution for this sort of problem is to extend the type.

extension Int {
    var isValid: Bool { return self > 1 || self == 0 }
}

if a.isValid { .... }

Right, there may be alternate solutions, of which one could be the proposed hypothetical syntax. Any thoughts about the syntax itself?

Testing one variable against multiple conditions is what the switch statement is designed for. (Though in your example with only two conditions and no else path, the if statement is still shorter.)

switch a {
case 2..., 0:
    print("...")
default:
    break
}

I understand the motivation for the syntax, but I prefer alternate solutions such as tucking a complex group of conditions into a property or using a switch statement. In other words, I don't see enough of a need for the syntax.

Absolutely true, and one of the main reasons this would never make it past a pitch. However, if this were composed with other logical statements not pertaining to a, it could still be useful over a switch. (Prepare yourself for an ugly contrived example)

if myVar (.isValid || .isMatch || < someOtherVar) && myOtherVar (== yetAnother && !.isHidden) { .... }

I just found the syntax to be interesting enough to share. Does anyone know if any language has implemented a similar feature? (Allowing the left hand side of a list of repeated logical expressions to be extracted out and applied to the list.)

Fair enough! Just an experiment :+1:

Et voilà, you can get very close to that already with a little cleverness. The following is operational in a playground:

struct Condition<T> {
    init(_ closure: @escaping (T) -> Bool) {
        evalute = closure
    }
    init(_ keyPath: KeyPath<T, Bool>) {
        evalute = { $0[keyPath: keyPath] }
    }
    let evalute: (T) -> Bool
}

// “element of” as a stand‐in for “matches one of”.
infix operator ∈ : ComparisonPrecedence
func ∈ <T>(lhs: T, rhs: [Condition<T>]) -> Bool {
    for condition in rhs where condition.evalute(lhs) {
        return true
    }
    return false
}

prefix operator >
prefix func > <T>(operand: T) -> Condition<T> where T : Comparable {
    return Condition({ $0 > operand })
}

prefix operator ==
prefix func == <T>(operand: T) -> Condition<T> where T : Comparable {
    return Condition({ $0 == operand })
}

let a = 0
// First example:
if a ∈ [>1, ==0] { /* ... */ }


extension Int {
    var isValid: Bool {
        return true
    }
    var isMatch: Bool {
        return false
    }
    var isHidden: Bool {
        return true
    }
}

// Something to wrap key paths. Reminiscent of the “.” for property access.
prefix operator ⋅
prefix func ⋅<T>(operand: KeyPath<T, Bool>) -> Condition<T> {
    return Condition(operand)
}

prefix operator .< // Lone “<” is not a valid prefix operator.
prefix func .< <T>(operand: T) -> Condition<T> where T : Comparable {
    return Condition({ $0 == operand })
}

// “is superset of” as a stand‐in for “matches all of”
infix operator ⊃ : ComparisonPrecedence
func ⊃ <T>(lhs: T, rhs: [Condition<T>]) -> Bool {
    for condition in rhs where !condition.evalute(lhs) {
        return false
    }
    return true
}

prefix func ! <T>(operand: Condition<T>) -> Condition<T> {
    return Condition({ !operand.evalute($0) })
}

let myVar = 1
let someOtherVar = 2
let myOtherVar = 3
let yetAnother = 4

// Latest example:
if myVar ∈ [⋅\.isValid, ⋅\.isMatch, .<someOtherVar]
    && myOtherVar ⊃ [==yetAnother, !(⋅\.isHidden)] {
    // ...
}
5 Likes

I'm seeing this just before going to sleep, but this is going to keep me up for a while longer! Hats off to you @SDGGiesbrecht for the clever implementation!

Terms of Service

Privacy Policy

Cookie Policy