Location of ! in Boolean negation expressions


(Phil Wigglesworth) #1

Moving the location of the ! will cause more readability problems,
particularly with confusion with the unwrap operator, and the fact that it
hides the negation operator in the middle of an expression.
A simple, very easily implemented solution needs not language change for
use with a guard statement: use a function against() that returns the
negated version of the express handed to it:

   func against(b:Bool)->Bool { return !b }.

For example:

   guard against( xyz == nil ) else { return }

This only partially works with the example:

guard !parameters.contains(where: { !validValueRange.contains($0) }) else …

“Make sure parameters does not contain an element such that
validValueRange does not contain this element.”

But after much thought, the author actually means "Guard against parameters
where an element is not in the validValueRange"

If we add a trivial function

   func isOutOfRange(element) { return !validValueRange.contains(element) }

then we can write a clearly readable and understandable piece of code:

   guard against( parameters.contains(where: isOutOfRange($0) ) ) else {
return }

which reads: "guard against parameters containing out of range elements."
Problem solved.

Here two helper functions-one general, one specific to this code-simplify
the code, without having to add to the complexity of the Swift Language.

···

From: Anton Zhilin <antonyzhilin@gmail.com>
To: Darren Mo <darren.mo@me.com>
Cc: swift-evolution <swift-evolution@swift.org>
Date: Sat, 6 Aug 2016 21:32:34 +0300
Subject: Re: [swift-evolution] Location of ! in Boolean negation expressions
2016-08-06 10:37 GMT+03:00 Darren Mo via swift-evolution < swift-evolution@swift.org>:

Consider code like

guard !parameters.contains(where: { !validValueRange.contains($0) }) else …

Oftentimes I need to write negation expressions like this. The location of
the exclamation marks really bugs me when writing and reading this code.
The natural English ordering would be something like

“Make sure parameters does not contain an element such that
validValueRange does not contain this element.”

against a parameter that has a validValueRange that does not contain this
element
guard against( parameters.contains(where: { !validValueRange.contains($)} )
) else ..

But the programming-language-imposed ordering is

“Make sure NOT parameters contains an element such that NOT
validValueRange contains this element.”

One solution to this problem would be to add negative method versions
wherever possible. For example: 'all', 'any', 'some', 'none' methods
instead of just 'contains(where:)'.
Plus, we could add 'unless' alongside 'guard'. But these features were
postponed to Stage 2.

On Sat, Aug 6, 2016 at 2:37 AM, Darren Mo via swift-evolution < swift-evolution@swift.org> wrote:

Consider code like

guard !parameters.contains(where: { !validValueRange.contains($0) }) else …

Oftentimes I need to write negation expressions like this. The location of
the exclamation marks really bugs me when writing and reading this code.
The natural English ordering would be something like

“Make sure parameters does not contain an element such that
validValueRange does not contain this element.”

But the programming-language-imposed ordering is

“Make sure NOT parameters contains an element such that NOT
validValueRange contains this element.”

See how much harder the programming language version is to understand?
Most of the time I write the positive version first because it comes out so
naturally, and then I add the exclamation marks afterwards. It really
burdens my mind every time I need to write code like this. Let’s come up
with a solution to address this!

Here’s my zero-thought solution:

guard parameters.!contains(where: { validValueRange.!contains($0) }) else …

I’d love to hear alternate solutions and whether other people are having
this problem too!

Darren
_______________________________________________