[Proposal] Add property for negation to Bool

I found negation operator (!) the least detectable among the code. So I’ve decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0 with extension:

extension BooleanType {
  var not: Bool { return !self.boolValue }
}

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while reading code. This happens less often with “not” property. So I’m proposing to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

2 Likes

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

I do agree with you that `!` is sometimes hard to notice, but I think putting the "not" at the end is sort of burying the lede—"if the lane at position y's current lane range contains a gap…NOT!" I don't like making `not(_:)` a function, and I don't think we should introduce a freestanding keyword just for this, either.

One workaround is to write this instead:

  return !!!self.lanes[position.y][currentLaneRange].contains(.Gap)

Three nots is logically equivalent to one, but far more visible. Of course, then you have to worry about accidentally writing two or four, which would be the opposite.

···

--
Brent Royal-Gordon
Architechies

1 Like

This would make sense as an operator (or actually it would have to be a keywod):

return not self.lanes[...].contains(.Gap)

Or if you don't mind having { } around the expression it could be defined as a function:

func not(@noescape block: (Void) -> Bool) rethrows -> Bool { return !block() }

Then you can have

return not { self.lanes[...].contains(.Gap) }

But I am personally not a fan of this.

Charlie

···

On May 21, 2016, at 4:50 PM, Антон Миронов via swift-evolution <swift-evolution@swift.org> wrote:

I found negation operator (!) the least detectable among the code. So I’ve decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0 with extension:

extension BooleanType {
  var not: Bool { return !self.boolValue }
}

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while reading code. This happens less often with “not” property. So I’m proposing to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Good point. In such a case it would be more rational to have “not" as func not(value Bool) -> Bool { … } . But I am not a fun of such solution either.
You see, in swift, there is a lot of code that looks like:

let newValue = rawValue
  .transformA(arg1) { ... }
  .transformB(arg2) { ... }
  .transformC(arg3) { ... }

It looks as a pipeline of transformations to me and I consider negation as one of those transformations. On the other hand negation operator totally breaks this pipeline. I personally prefer a bit longer list of transformations rather than list of transformations and negation operator as prefix to the list.

···

21 трав. 2016 р. о 17:59 Charlie Monroe <charlie@charliemonroe.net> написав(ла):

This would make sense as an operator (or actually it would have to be a keywod):

return not self.lanes[...].contains(.Gap)

Or if you don't mind having { } around the expression it could be defined as a function:

func not(@noescape block: (Void) -> Bool) rethrows -> Bool { return !block() }

Then you can have

return not { self.lanes[...].contains(.Gap) }

But I am personally not a fan of this.

Charlie

On May 21, 2016, at 4:50 PM, Антон Миронов via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I found negation operator (!) the least detectable among the code. So I’ve decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0 with extension:

extension BooleanType {
  var not: Bool { return !self.boolValue }
}

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while reading code. This happens less often with “not” property. So I’m proposing to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I'm going to courteously disagree. The not operator belongs on the leading edge and not the trailing edge of the expression:

* One writes ~TruthValue, ¬TruthValue, "not TruthValue", etc.
* One does not write TruthValue~, TruthValue¬, or "TruthValue not".

Reading code under the current system creates phrases like "if-not expression", naturally conjoining "if not". Under your proposed system, it reads as "if expression not" or "if expression negated truth value". This places a higher cognitive burden on the person reading the code and delays recognition that an expression should be understood in its inverse form. I think it's *more* likely a code reader would miss the intent in scanning than they would miss the leading exclamation point which, although small, is common and often used. As for using a property, such as ".not", ".negativeTruthValue", etc., although it makes the operation bigger and more noticeable, it does so in the wrong place, and inelegantly.

I wouldn't support introducing a `not` keyword as in `if not expression` as this does not feel "Swifty". It is neither concise, or more clear. All in all, this feels like a fix for something that isn't broken, and I cannot see any real world measurable benefit from changing the leading not operator. I believe the impact of the change would be larger than expected and to the detriment of the language.

-- E

···

On May 21, 2016, at 8:50 AM, Антон Миронов via swift-evolution <swift-evolution@swift.org> wrote:

I found negation operator (!) the least detectable among the code. So I’ve decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0 with extension:

extension BooleanType {
  var not: Bool { return !self.boolValue }
}

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while reading code. This happens less often with “not” property. So I’m proposing to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

2 Likes

I think this would make more sense if we were to get more characters in operators, such that we could also replace && with and, and || with or, this way we could make not an operator and write expressions like so:

  if foo and not bar { … }

Otherwise as others have said this seems strange as a method. If you don’t find the leading exclamation mark very readable then you could instead do:

  foo != true

It’s a few more characters, but it exists now and reads logically I think.

···

On 21 May 2016, at 15:50, Антон Миронов via swift-evolution <swift-evolution@swift.org> wrote:

I found negation operator (!) the least detectable among the code. So I’ve decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0 with extension:

extension BooleanType {
  var not: Bool { return !self.boolValue }
}

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while reading code. This happens less often with “not” property. So I’m proposing to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I think having the “not” up at the front of the boolean condition is
useful. Think about why this joke works:

    “I'm a big fan of reference semantics... NOT!”

···

on Sat May 21 2016, Антон Миронов <swift-evolution@swift.org> wrote:

I found negation operator (!) the least detectable among the code. So
I’ve decided to add property “not” to BooleanType (Swift 2.2) or
Boolean on 3.0 with extension:

extension BooleanType {
  var not: Bool { return !self.boolValue }
}

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first
it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

--
-Dave

2 Likes

I appreciate your support but looks like this proposal is going nowhere. This proposal affects fundamental habits that are very hard to argue with.
Never the less I will keep using this property in my code because my team is okay with it.

Thanks,
Anton Mironov

···

6 черв. 2016 р. о 21:42 Thorsten Seitz <tseitz42@icloud.com> написав(ла):

That's just the way it was done in Smalltalk. Very readable IMHO as I'm not a fan of `!` either for the reasons you cited.

-Thorsten

Am 21.05.2016 um 16:50 schrieb Антон Миронов via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

I found negation operator (!) the least detectable among the code. So I’ve decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0 with extension:

extension BooleanType {
  var not: Bool { return !self.boolValue }
}

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while reading code. This happens less often with “not” property. So I’m proposing to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

1 Like

If you have a pipeline like this, I'd suggest to break it up into smaller segments also for the sake of readability...

The `not` var just doesn't seem right to me. Perhaps negatedValue? negatedBoolValue, since BooleanType has boolValue?

Question is whether this should be implemented on BooleanType or directly on Bool.

But I still have mixed feelings about this.

Charlie

···

On May 21, 2016, at 5:42 PM, Антон Миронов <antonvmironov@gmail.com> wrote:

Good point. In such a case it would be more rational to have “not" as func not(value Bool) -> Bool { … } . But I am not a fun of such solution either.
You see, in swift, there is a lot of code that looks like:

let newValue = rawValue
  .transformA(arg1) { ... }
  .transformB(arg2) { ... }
  .transformC(arg3) { ... }

It looks as a pipeline of transformations to me and I consider negation as one of those transformations. On the other hand negation operator totally breaks this pipeline. I personally prefer a bit longer list of transformations rather than list of transformations and negation operator as prefix to the list.

21 трав. 2016 р. о 17:59 Charlie Monroe <charlie@charliemonroe.net <mailto:charlie@charliemonroe.net>> написав(ла):

This would make sense as an operator (or actually it would have to be a keywod):

return not self.lanes[...].contains(.Gap)

Or if you don't mind having { } around the expression it could be defined as a function:

func not(@noescape block: (Void) -> Bool) rethrows -> Bool { return !block() }

Then you can have

return not { self.lanes[...].contains(.Gap) }

But I am personally not a fan of this.

Charlie

On May 21, 2016, at 4:50 PM, Антон Миронов via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I found negation operator (!) the least detectable among the code. So I’ve decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0 with extension:

extension BooleanType {
  var not: Bool { return !self.boolValue }
}

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while reading code. This happens less often with “not” property. So I’m proposing to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

1 Like

`var isFalse: Bool` seems like a nice resolution to me. no need for new
keywords and it reads better than !foo

···

On Sun, May 22, 2016 at 3:28 AM, Haravikk via swift-evolution < swift-evolution@swift.org> wrote:

I think this would make more sense if we were to get more characters in
operators, such that we could also replace && with and, and || with or,
this way we could make not an operator and write expressions like so:

if foo and not bar { … }

Otherwise as others have said this seems strange as a method. If you don’t
find the leading exclamation mark very readable then you could instead do:

foo != true

It’s a few more characters, but it exists now and reads logically I think.

On 21 May 2016, at 15:50, Антон Миронов via swift-evolution < > swift-evolution@swift.org> wrote:

I found negation operator (!) the least detectable among the code. So I’ve
decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0
with extension:

extension BooleanType {
var not: Bool { return !self.boolValue }
}

This is code with negation operator:
return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it
looks like I’m trying to negate self for some reason.

This is code with “not” property:
return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while
reading code. This happens less often with “not” property. So I’m proposing
to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

3 Likes

If there is a proposal for this, I think it needs to be complete - i.e. adding:

var isFalse: Bool
var isTrue: Bool
var negatedValue: Self (on BooleanType)
var negatedBoolValue: Bool

In such terms, the BooleanType would be complete as you'd be able to express all boolean operations using functions/properties. The question is where would it be used. I do not think adding a negating variable at the end of several transformations is a good idea, perhaps something like this could be used in predicate programming...

···

On May 22, 2016, at 9:30 AM, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:

`var isFalse: Bool` seems like a nice resolution to me. no need for new keywords and it reads better than !foo

On Sun, May 22, 2016 at 3:28 AM, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I think this would make more sense if we were to get more characters in operators, such that we could also replace && with and, and || with or, this way we could make not an operator and write expressions like so:

  if foo and not bar { … }

Otherwise as others have said this seems strange as a method. If you don’t find the leading exclamation mark very readable then you could instead do:

  foo != true

It’s a few more characters, but it exists now and reads logically I think.

On 21 May 2016, at 15:50, Антон Миронов via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I found negation operator (!) the least detectable among the code. So I’ve decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0 with extension:

extension BooleanType {
  var not: Bool { return !self.boolValue }
}

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while reading code. This happens less often with “not” property. So I’m proposing to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

1 Like

You are completely right about ¬TruthValue. Going further I would say that in math list of transform looks like this:

  transformC(transformB(transformA(value)))

Negation operator fits perfectly in such notation. But since Swift 2 language moved to notation:

  value.transformA.transformB.transformC

This notation is inverse to the one we see in math. So in my opinion negation property fits in new Swift notation as another transformation appended to others.

I agree that negation operator looks better for “if !value” such as:

let containsEvenNumers = numbers.contains { ($0 % 2) == 0 }
if !containsEvenNumers {
  print(“No even numbers here")
}

Because in this case you directly negate “containsEvenNumers”. But in case:

func isEven(number: Int) -> Bool { return (number % 2) == 0 }

if !numbers.contains(isEven) {
  print(“No even numbers here")
}

negation operator actually has higher cognitive burden to me. I have to remember about prefix when I’m just trying to read expression from left to right.

On the other hand, negation property that looks like consecutive transformation lets me read expression in one direction. And since I’m used to reading expressions to the end it is easy to notice negation at the end.

func isEven(number: Int) -> Bool { return (number % 2) == 0 }
if numbers.contains(isEven).not {
  print(“No even numbers here")
}

Maybe this question goes too deep. Or maybe unidirectional instruction flow is not that important.

Thanks,
Anton Mironov

···

22 трав. 2016 р. о 04:14 Erica Sadun <erica@ericasadun.com> написав(ла):

I'm going to courteously disagree. The not operator belongs on the leading edge and not the trailing edge of the expression:

* One writes ~TruthValue, ¬TruthValue, "not TruthValue", etc.
* One does not write TruthValue~, TruthValue¬, or "TruthValue not".

Reading code under the current system creates phrases like "if-not expression", naturally conjoining "if not". Under your proposed system, it reads as "if expression not" or "if expression negated truth value". This places a higher cognitive burden on the person reading the code and delays recognition that an expression should be understood in its inverse form. I think it's *more* likely a code reader would miss the intent in scanning than they would miss the leading exclamation point which, although small, is common and often used. As for using a property, such as ".not", ".negativeTruthValue", etc., although it makes the operation bigger and more noticeable, it does so in the wrong place, and inelegantly.

I wouldn't support introducing a `not` keyword as in `if not expression` as this does not feel "Swifty". It is neither concise, or more clear. All in all, this feels like a fix for something that isn't broken, and I cannot see any real world measurable benefit from changing the leading not operator. I believe the impact of the change would be larger than expected and to the detriment of the language.

-- E

On May 21, 2016, at 8:50 AM, Антон Миронов via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I found negation operator (!) the least detectable among the code. So I’ve decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0 with extension:

extension BooleanType {
  var not: Bool { return !self.boolValue }
}

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while reading code. This happens less often with “not” property. So I’m proposing to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Fun as this conversation is, replacing "!" with "not" and other related
changes ("&&" replaced with "and", etc.) represent a commonly proposed and
rejected change
<https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md&gt;,
and the rationale is given here
<https://lists.swift.org/pipermail/swift-evolution/2015-December/000032.html&gt;
.

···

On Sun, May 22, 2016 at 1:15 PM, Dave Abrahams via swift-evolution < swift-evolution@swift.org> wrote:

on Sat May 21 2016, Антон Миронов <swift-evolution@swift.org> wrote:

> I found negation operator (!) the least detectable among the code. So
> I’ve decided to add property “not” to BooleanType (Swift 2.2) or
> Boolean on 3.0 with extension:
>
> extension BooleanType {
> var not: Bool { return !self.boolValue }
> }
>
> This is code with negation operator:
> return !self.lanes[position.y][currentLaneRange].contains(.Gap)
>
> As I sad before negation operation is hard to spot. Moreover at first
> it looks like I’m trying to negate self for some reason.
>
> This is code with “not” property:
> return self.lanes[position.y][currentLaneRange].contains(.Gap).not

I think having the “not” up at the front of the boolean condition is
useful. Think about why this joke works:

    “I'm a big fan of reference semantics... NOT!”

--
-Dave

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

1 Like

`negated` or `negatedValue` or `negatedBoolValue` looks good to me too.

I think that it should be implemented on BooleanType because you do not want to consider whether it is Bool or DarwinBoolean or ObjCBool when just need a negated value.

I also understand your mixed feelings because negation operator is so familiar to every developer. I suggest you to try using negation property on real code for a bit.

Code readability is a very important. But in my opinion pipelining can be more expressive in some cases. But this discussion is off topic.

···

21 трав. 2016 р. о 19:49 Charlie Monroe <charlie@charliemonroe.net> написав(ла):

If you have a pipeline like this, I'd suggest to break it up into smaller segments also for the sake of readability...

The `not` var just doesn't seem right to me. Perhaps negatedValue? negatedBoolValue, since BooleanType has boolValue?

Question is whether this should be implemented on BooleanType or directly on Bool.

But I still have mixed feelings about this.

Charlie

On May 21, 2016, at 5:42 PM, Антон Миронов <antonvmironov@gmail.com <mailto:antonvmironov@gmail.com>> wrote:

Good point. In such a case it would be more rational to have “not" as func not(value Bool) -> Bool { … } . But I am not a fun of such solution either.
You see, in swift, there is a lot of code that looks like:

let newValue = rawValue
  .transformA(arg1) { ... }
  .transformB(arg2) { ... }
  .transformC(arg3) { ... }

It looks as a pipeline of transformations to me and I consider negation as one of those transformations. On the other hand negation operator totally breaks this pipeline. I personally prefer a bit longer list of transformations rather than list of transformations and negation operator as prefix to the list.

21 трав. 2016 р. о 17:59 Charlie Monroe <charlie@charliemonroe.net <mailto:charlie@charliemonroe.net>> написав(ла):

This would make sense as an operator (or actually it would have to be a keywod):

return not self.lanes[...].contains(.Gap)

Or if you don't mind having { } around the expression it could be defined as a function:

func not(@noescape block: (Void) -> Bool) rethrows -> Bool { return !block() }

Then you can have

return not { self.lanes[...].contains(.Gap) }

But I am personally not a fan of this.

Charlie

On May 21, 2016, at 4:50 PM, Антон Миронов via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I found negation operator (!) the least detectable among the code. So I’ve decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0 with extension:

extension BooleanType {
  var not: Bool { return !self.boolValue }
}

This is code with negation operator:
  return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it looks like I’m trying to negate self for some reason.

This is code with “not” property:
  return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while reading code. This happens less often with “not” property. So I’m proposing to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

1 Like

Or .isFalse :)

···

On Sat, May 21, 2016 at 10:22 AM Антон Миронов <swift-evolution@swift.org> wrote:

`negated` or `negatedValue` or `negatedBoolValue` looks good to me too.

I think that it should be implemented on BooleanType because you do not
want to consider whether it is Bool or DarwinBoolean or ObjCBool when just
need a negated value.

I also understand your mixed feelings because negation operator is so
familiar to every developer. I suggest you to try using negation property
on real code for a bit.

Code readability is a very important. But in my opinion pipelining can be
more expressive in some cases. But this discussion is off topic.

21 трав. 2016 р. о 19:49 Charlie Monroe <charlie@charliemonroe.net>
написав(ла):

If you have a pipeline like this, I'd suggest to break it up into smaller
segments also for the sake of readability...

The `not` var just doesn't seem right to me. Perhaps negatedValue?
negatedBoolValue, since BooleanType has boolValue?

Question is whether this should be implemented on BooleanType or directly
on Bool.

But I still have mixed feelings about this.

Charlie

On May 21, 2016, at 5:42 PM, Антон Миронов <antonvmironov@gmail.com> > wrote:

Good point. In such a case it would be more rational to have “not" as func
not(value Bool) -> Bool { … } . But I am not a fun of such solution either.
You see, in swift, there is a lot of code that looks like:

let newValue = rawValue
.transformA(arg1) { ... }
.transformB(arg2) { ... }
.transformC(arg3) { ... }

It looks as a pipeline of transformations to me and I consider negation as
one of those transformations. On the other hand negation operator totally
breaks this pipeline. I personally prefer a bit longer list of
transformations rather than list of transformations and negation operator
as prefix to the list.

21 трав. 2016 р. о 17:59 Charlie Monroe <charlie@charliemonroe.net>
написав(ла):

This would make sense as an operator (or actually it would have to be a
keywod):

return not self.lanes[...].contains(.Gap)

Or if you don't mind having { } around the expression it could be defined
as a function:

func not(@noescape block: (Void) -> Bool) rethrows -> Bool { return
!block() }

Then you can have

return not { self.lanes[...].contains(.Gap) }

But I am personally not a fan of this.

Charlie

On May 21, 2016, at 4:50 PM, Антон Миронов via swift-evolution < > swift-evolution@swift.org> wrote:

I found negation operator (!) the least detectable among the code. So I’ve
decided to add property “not” to BooleanType (Swift 2.2) or Boolean on 3.0
with extension:

extension BooleanType {
var not: Bool { return !self.boolValue }
}

This is code with negation operator:
return !self.lanes[position.y][currentLaneRange].contains(.Gap)

As I sad before negation operation is hard to spot. Moreover at first it
looks like I’m trying to negate self for some reason.

This is code with “not” property:
return self.lanes[position.y][currentLaneRange].contains(.Gap).not

Now it is easy to spot the statement I am actually getting negation of.
On my experience negation operator can occasionally be missed while
reading code. This happens less often with “not” property. So I’m proposing
to add this property to standard library and prefer it in most cases.

Thanks,
Anton Mironov

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

1 Like

Fun as this conversation is, replacing "!" with "not" and other related
changes ("&&" replaced with "and", etc.) represent a commonly proposed and
rejected change
<https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md >,
and the rationale is given here
<https://lists.swift.org/pipermail/swift-evolution/2015-December/000032.html >
.

I disagree that the links provided by @xwu refer to the top in question. Those discussions refer to replace the existing not operator with the english word for "not."

Five years later there is still a need for such a negation property on bool particulaly in functional programming use cases.

Current solutions involve writing an extension on bool. E.g.

extension Bool {
    var negated: Bool { !self }
}
let string = "abc12345" 
let nonDigits = string.filter(\.isWholeNumber.negated) // "abc"

The alternative would be to write let nonDigits = string.filter { !$0.isWholeNumber } // "abc" today.

There are clear drawbacks to this approach in light of the introduction of key paths in more recent Swift versions published since the start of this thread.

  1. Using key paths removes the need to adopt anonymous closure arguments, which impair readability. Named closure arguments on the other hand would be a detriment to brevity. Neither is a great solution when possibilities exist that cleanly avoid both drawbacks.
  2. Requiring curly braces means that when used in an if-let or guard-let statement, the filter argument would need to further be wrapped in parentheses. This impairs reading and writing the code.

Declaring an extension on Bool such as isFalse or negated would be trivial. As it is something that could widely benefit the Swift developer community, personally, I see no reason for it not to be adopted into the standard library.

What other alternatives that have not been discussed here, if any?

1 Like

won't fly, but still big fat +1 from me. i like "not" (and postfix boolean negation of other forms) on many fronts. sometimes i even go into trouble and introduce my own <> and my own flavour of "not" (the form or shape of which depends upon my mood on the day, ranging from postfix "not" to prefix ¬ (option + L on my keyboard, YMMV). the benefits are numerous:

  • works in jokes - works here.
  • more "fluent"
  • eases grasping complex expressions (left to right reasoning).
  • along with <> leaves "!" to be associated with optional unwrapping only, and thus highlights and makes them more outstanding.

now that we have "toggle()" the spelling for "not" could be "toggled".

having said that, i don't believe it would be possible to introduce this change to the language at this point. 5 years ago - perhaps, now - too big inertia and there'll be too much backlash.

let string = "abc12345" 
let nonDigits = string.filter(\.isWholeNumber.negated) // "abc"

I definitely see this use case, but perhaps a better approach is to define a ! that operates on KeyPaths and/or functions that return Bool?

2 Likes

perhaps a better approach is to define a ! that operates on KeyPaths and/or functions that return Bool?

This ideas sounds fantastic to me, if only for the reason of not introducing more ways (ie. .toggled, .not or isNot).