Limit checking syntax


(Maury Markowitz) #1

I originally posted this in swift-users, and it garnered some level of positive reaction, so I thought I would try it again here.

We all constantly write code that checks a value against arbitrary ranges - subsets of an array, characters within a string, etc. This is a common example:

if myVal >= oneLimit && myVar <= twoLimit { // something }

Swift introduced a very nice range system that is used to represent these sorts of spans-within-limits, which greatly clarifies common code like this...

for c in cards[0..<10] { // something }

My proposal is that this same "in" syntax be allowed in an if statement. Thus the limit check above would become:

if myVal in [oneLimit...twoLimit] { // something }

The code is somewhat more terse, which is a common goal in Swift. It also more clearly states what the purpose of the code - this is a range check, not some arbitrary mathematical comparisons. It also has the advantage that if myVal is expensive, a func for instance, it only gets evaluated once. Effectively it replaces:

let myVal = someExpensiveFunction()
if myVal >= oneLimit && myVar <= twoLimit...

with a single line of code.

I note that there are ways to accomplish this already in Swift 2, but I find them unsatisfying, and somewhat unnatural. They are definitely not "discoverable". which I believe the in statement would be. The current solution is the pattern-matching if, like this:

if case 0...100 = someInteger

or

if 0...100 ~= someInteger

I see two problems with this approach. Once is that the "if case" structure strikes me somewhat odd on it's own, but more specifically I think everyone finds the syntax "backward", we normally code the tested item on the left and limits on the right, and this reversal seems unnatural to me (in spite of it being identical in code terms). But I think the real issue is that both examples require special syntax that is very different than other languages or even most constructs in Swift itself, whereas in is already used in exactly the fashion I propose.

I don't believe that re-using "in" would greatly burden the language, while offering the same behaviour as the pattern-matching-if in a much more natural and already-used syntax.


(Harlan Haskins) #2

I’ve found that .contains works well for all my uses.

(0..<100).contains(x)

···

On Apr 7, 2016, at 1:17 PM, Maury Markowitz via swift-evolution <swift-evolution@swift.org> wrote:

I originally posted this in swift-users, and it garnered some level of positive reaction, so I thought I would try it again here.

We all constantly write code that checks a value against arbitrary ranges - subsets of an array, characters within a string, etc. This is a common example:

if myVal >= oneLimit && myVar <= twoLimit { // something }

Swift introduced a very nice range system that is used to represent these sorts of spans-within-limits, which greatly clarifies common code like this...

for c in cards[0..<10] { // something }

My proposal is that this same "in" syntax be allowed in an if statement. Thus the limit check above would become:

if myVal in [oneLimit...twoLimit] { // something }

The code is somewhat more terse, which is a common goal in Swift. It also more clearly states what the purpose of the code - this is a range check, not some arbitrary mathematical comparisons. It also has the advantage that if myVal is expensive, a func for instance, it only gets evaluated once. Effectively it replaces:

let myVal = someExpensiveFunction()
if myVal >= oneLimit && myVar <= twoLimit...

with a single line of code.

I note that there are ways to accomplish this already in Swift 2, but I find them unsatisfying, and somewhat unnatural. They are definitely not "discoverable". which I believe the in statement would be. The current solution is the pattern-matching if, like this:

if case 0...100 = someInteger

or

if 0...100 ~= someInteger

I see two problems with this approach. Once is that the "if case" structure strikes me somewhat odd on it's own, but more specifically I think everyone finds the syntax "backward", we normally code the tested item on the left and limits on the right, and this reversal seems unnatural to me (in spite of it being identical in code terms). But I think the real issue is that both examples require special syntax that is very different than other languages or even most constructs in Swift itself, whereas in is already used in exactly the fashion I propose.

I don't believe that re-using "in" would greatly burden the language, while offering the same behaviour as the pattern-matching-if in a much more natural and already-used syntax.

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


(Vladimir) #3

Hmm.. Isn't next construction is much more readable?:

x.in(0..<100)

I think it is much more readable.
We are planning(in head) to verify "if x value is in range from 0 up to 99", so why we have to write "for some range 0 to 9 let's check if it contains our x value".
Our x is a subject of our check, not range (0..<100).

I.e. in my opinion -1 for 'in' operator like suggested in initial message,
but +1 for .in method for integer to check against range
Any additional opinion?

Vladimir
(P.S. Sorry for duplicate.)

···

On 08.04.2016 4:14, Harlan Haskins via swift-evolution wrote:
> I’ve found that .contains works well for all my uses.
>
> (0..<100).contains(x)


(Dave Abrahams) #4

I’ve found that .contains works well for all my uses.

(0..<100).contains(x)

Hmm.. Isn't next construction is much more readable?:

x.in(0..<100)

API guidelines prescribe this should read as an assertion about x, so:

     x.isContainedIn(0..<100)

or

     x.isIn(0..<100)

FWIW.

···

on Fri Apr 08 2016, "Vladimir.S via swift-evolution" <swift-evolution@swift.org> wrote:

On 08.04.2016 4:14, Harlan Haskins via swift-evolution wrote:

I think it is much more readable.
We are planning(in head) to verify "if x value is in range from 0 up
to 99", so why we have to write "for some range 0 to 9 let's check if
it contains our x value".
Our x is a subject of our check, not range (0..<100).

I.e. in my opinion -1 for 'in' operator like suggested in initial message,
but +1 for .in method for integer to check against range
Any additional opinion?

Vladimir
(P.S. Sorry for duplicate.)
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Dave


(Vladimir) #5

100% Agree. IMO .isIn is perfect :slight_smile:
I think the main idea is to allow us to check bounds of some value(usually integer) in nice and readable manner.

···

On 08.04.2016 21:21, Dave Abrahams via swift-evolution wrote:

API guidelines prescribe this should read as an assertion about x, so:

      x.isContainedIn(0..<100)

or

      x.isIn(0..<100)