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

Et voilà, 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!