Arrays Returning Optionals instead of Index Out of Bounds


(Rob Norback) #1

Hi Everyone!

This is my first time emailing the swift evolution list, so if this topic
has already been discussed please let me know. I looked through all the
accepted and rejected proposals and it doesn't seem to be on there.

The main thought is that dictionaries return optionals, so why not arrays?
Or other CollectionTypes for that matter. I would think this would be the
expected behavior in this situation:

var myArray:[String?] = []
print(myArray[4])
// EXC_BAD_INSTRUCTION, but could just be Optional(nil)

Then you could do things like

if let arrayValue = myArray[4] {
   // do something
}

Of course you could simply check with with the count, but considering
Swift's use of optionals to represent empty variables rather than erroring
out or returning an empty String, I think this functionality would be
appropriate to include in the Swift standard library.

And there's about 15,000 people who've looked for this functionality in the
last year:
http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings
.

Please let me know what you think.

Best,
Rob Norback


(Vladimir) #2

Please find this draft of proposal(hope this is correct link for latest version):
https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

The main idea is to introduce 2 new subscript methods: [clamping:] and [checking:]

There was discussion in "[Proposal] More lenient subscript methods over Collections" and (older) "[Proposal] Safer half-open range operator"

···

On 06.06.2016 19:50, Rob Norback via swift-evolution wrote:

Hi Everyone!

This is my first time emailing the swift evolution list, so if this topic
has already been discussed please let me know. I looked through all the
accepted and rejected proposals and it doesn't seem to be on there.

The main thought is that dictionaries return optionals, so why not arrays?
Or other CollectionTypes for that matter. I would think this would be the
expected behavior in this situation:

var myArray:[String?] = []
print(myArray[4])
// EXC_BAD_INSTRUCTION, but could just be Optional(nil)

Then you could do things like

if let arrayValue = myArray[4] {
   // do something
}

Of course you could simply check with with the count, but considering
Swift's use of optionals to represent empty variables rather than erroring
out or returning an empty String, I think this functionality would be
appropriate to include in the Swift standard library.

And there's about 15,000 people who've looked for this functionality in the
last year:
http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings.

Please let me know what you think.

Best,
Rob Norback

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


(Christopher Kornher) #3

The proposal needs to discuss arrays of optionals e.g.: ```Array<Int?>```
These are not just legal, they are quite handy as well.

Dictionaries can also be declared with optional values, of course: ```Dictionary<Int,Int?>```
These can be pretty confusing to deal with and we should not add to confusion with arrays.

An example of the confusion:

var d = Dictionary<Int,Int?>
...
d[0] = nil // Does this delete the element or set it to nil? Honestly, I forget. The point is, the syntax is ambiguous.

It would be nice to create a completely unambiguous syntax for collections with optional values.

- Chris K

···

On Jun 6, 2016, at 11:10 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

Please find this draft of proposal(hope this is correct link for latest version):
https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

The main idea is to introduce 2 new subscript methods: [clamping:] and [checking:]

There was discussion in "[Proposal] More lenient subscript methods over Collections" and (older) "[Proposal] Safer half-open range operator"

On 06.06.2016 19:50, Rob Norback via swift-evolution wrote:

Hi Everyone!

This is my first time emailing the swift evolution list, so if this topic
has already been discussed please let me know. I looked through all the
accepted and rejected proposals and it doesn't seem to be on there.

The main thought is that dictionaries return optionals, so why not arrays?
Or other CollectionTypes for that matter. I would think this would be the
expected behavior in this situation:

var myArray:[String?] = []
print(myArray[4])
// EXC_BAD_INSTRUCTION, but could just be Optional(nil)

Then you could do things like

if let arrayValue = myArray[4] {
  // do something
}

Of course you could simply check with with the count, but considering
Swift's use of optionals to represent empty variables rather than erroring
out or returning an empty String, I think this functionality would be
appropriate to include in the Swift standard library.

And there's about 15,000 people who've looked for this functionality in the
last year:
http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings.

Please let me know what you think.

Best,
Rob Norback

_______________________________________________
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


(Christopher Kornher) #4

First of all, thank you all for bringing me up to date so quickly. I looked over the proposal and it looks awesome.

But as Chris mentioned, this doesn't solve the expected behavior and ambiguity of ```Array<Int?>```

I think that name is reserved word on this list :slight_smile: Just to be clear, I am another Chris (Chris K).
I forgot to mention that I like the proposal.

In this case I would expect the default behavior (myArray[4]) without using myArray[checking: 4] should return a nil in this case.

And Chris, I think it would make the most sense to have myArray[0] = nil to be stored if the index is in Range, and for myArray[100] = nil to give a warning of no assignment being made because index is out of range, kind of like an unused variable. Right now myArray[100] = nil gives you EXC_BAD_INSTRUCTION. Then if you assigned myArray[100] = 200, that would have to simply change the Range.

Yes, Arrays should store the value and I do not believe that the syntax for allays would be ambiguous. I do believe that since this is in the same general territory, the syntax for dictionaries should be improved at the same time, to simplify the story for users… perhaps with another keyword(?)

var d = Dictionary<Int,Int?>
...
d[setting:0] = nil		// I did not give much thought to the name of the keyword.

A solution that uses the same new syntax should probably be in the same proposal. A separate proposal might be more appropriate for a different solution.

···

On Jun 6, 2016, at 12:02 PM, Rob Norback via swift-evolution <swift-evolution@swift.org> wrote:

Chris, I honestly have to think more about that ambiguity with dictionaries.

I can see that this would definitely need some further fleshing out, but it seems to be sufficiently different from Luis' proposal to perhaps merit it's own proposal.

It's up to you Luis, but I think this might be a bit more controversial then the changes you've proposed, making it possible for your proposal getting rejected. (I want your proposal accepted, since I would use those features today). Partial acceptance of a proposal doesn't seem to be a thing. (Once again please correct me if I'm wrong).

On Mon, Jun 6, 2016 at 11:46 AM Luis Henrique B. Sousa <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:
Thanks Vladimir,

The correct link is this one (with the additional min/max operations in the implementation):
https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

Here is the pull request on the swift-evolution repo: https://github.com/apple/swift-evolution/pull/328

Any help or suggestion to improve the proposal is welcome. :slight_smile:

- Luis

On Mon, Jun 6, 2016 at 6:10 PM, Vladimir.S via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Please find this draft of proposal(hope this is correct link for latest version):
https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

The main idea is to introduce 2 new subscript methods: [clamping:] and [checking:]

There was discussion in "[Proposal] More lenient subscript methods over Collections" and (older) "[Proposal] Safer half-open range operator"

On 06.06.2016 19:50, Rob Norback via swift-evolution wrote:
Hi Everyone!

This is my first time emailing the swift evolution list, so if this topic
has already been discussed please let me know. I looked through all the
accepted and rejected proposals and it doesn't seem to be on there.

The main thought is that dictionaries return optionals, so why not arrays?
Or other CollectionTypes for that matter. I would think this would be the
expected behavior in this situation:

var myArray:[String?] = []
print(myArray[4])
// EXC_BAD_INSTRUCTION, but could just be Optional(nil)

Then you could do things like

if let arrayValue = myArray[4] {
   // do something
}

Of course you could simply check with with the count, but considering
Swift's use of optionals to represent empty variables rather than erroring
out or returning an empty String, I think this functionality would be
appropriate to include in the Swift standard library.

And there's about 15,000 people who've looked for this functionality in the
last year:
http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings.

Please let me know what you think.

Best,
Rob Norback

_______________________________________________
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


(Rob Norback) #5

First of all, thank you all for bringing me up to date so quickly. I
looked over the proposal and it looks awesome.

But as Chris mentioned, this doesn't solve the expected behavior and
ambiguity of ```Array<Int?>```

In this case I would expect the default behavior (myArray[4]) without using
myArray[checking: 4] should return a nil in this case.

And Chris, I think it would make the most sense to have myArray[0] = nil to
be stored if the index is in Range, and for myArray[100] = nil to give a
warning of no assignment being made because index is out of range, kind of
like an unused variable. Right now myArray[100] = nil gives you
EXC_BAD_INSTRUCTION. Then if you assigned myArray[100] = 200, that would
have to simply change the Range.

Chris, I honestly have to think more about that ambiguity with dictionaries.

I can see that this would definitely need some further fleshing out, but it
seems to be sufficiently different from Luis' proposal to perhaps merit
it's own proposal.

It's up to you Luis, but I think this might be a bit more controversial
then the changes you've proposed, making it possible for your proposal
getting rejected. (I want your proposal accepted, since I would use those
features today). Partial acceptance of a proposal doesn't seem to be a
thing. (Once again please correct me if I'm wrong).

···

On Mon, Jun 6, 2016 at 11:46 AM Luis Henrique B. Sousa <lshsousa@gmail.com> wrote:

Thanks Vladimir,

The correct link is this one (with the additional min/max operations in
the implementation):

https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

Here is the pull request on the swift-evolution repo:
https://github.com/apple/swift-evolution/pull/328

Any help or suggestion to improve the proposal is welcome. :slight_smile:

- Luis

On Mon, Jun 6, 2016 at 6:10 PM, Vladimir.S via swift-evolution < > swift-evolution@swift.org> wrote:

Please find this draft of proposal(hope this is correct link for latest
version):

https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

The main idea is to introduce 2 new subscript methods: [clamping:] and
[checking:]

There was discussion in "[Proposal] More lenient subscript methods over
Collections" and (older) "[Proposal] Safer half-open range operator"

On 06.06.2016 19:50, Rob Norback via swift-evolution wrote:

Hi Everyone!

This is my first time emailing the swift evolution list, so if this topic
has already been discussed please let me know. I looked through all the
accepted and rejected proposals and it doesn't seem to be on there.

The main thought is that dictionaries return optionals, so why not
arrays?
Or other CollectionTypes for that matter. I would think this would be
the
expected behavior in this situation:

var myArray:[String?] = []
print(myArray[4])
// EXC_BAD_INSTRUCTION, but could just be Optional(nil)

Then you could do things like

if let arrayValue = myArray[4] {
   // do something
}

Of course you could simply check with with the count, but considering
Swift's use of optionals to represent empty variables rather than
erroring
out or returning an empty String, I think this functionality would be
appropriate to include in the Swift standard library.

And there's about 15,000 people who've looked for this functionality in
the
last year:

http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings
.

Please let me know what you think.

Best,
Rob Norback

_______________________________________________
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


(Rob Norback) #6

Apologies, please remove the line "Right now myArray[100] = nil gives you
EXC_BAD_INSTRUCTION." from my previous email so it makes more sense to read.

···

On Mon, Jun 6, 2016 at 12:02 PM Rob Norback <rnorback@gmail.com> wrote:

First of all, thank you all for bringing me up to date so quickly. I
looked over the proposal and it looks awesome.

But as Chris mentioned, this doesn't solve the expected behavior and
ambiguity of ```Array<Int?>```

In this case I would expect the default behavior (myArray[4]) without
using myArray[checking: 4] should return a nil in this case.

And Chris, I think it would make the most sense to have myArray[0] = nil
to be stored if the index is in Range, and for myArray[100] = nil to give a
warning of no assignment being made because index is out of range, kind of
like an unused variable. Right now myArray[100] = nil gives you
EXC_BAD_INSTRUCTION. Then if you assigned myArray[100] = 200, that would
have to simply change the Range.

Chris, I honestly have to think more about that ambiguity with
dictionaries.

I can see that this would definitely need some further fleshing out, but
it seems to be sufficiently different from Luis' proposal to perhaps merit
it's own proposal.

It's up to you Luis, but I think this might be a bit more controversial
then the changes you've proposed, making it possible for your proposal
getting rejected. (I want your proposal accepted, since I would use those
features today). Partial acceptance of a proposal doesn't seem to be a
thing. (Once again please correct me if I'm wrong).

On Mon, Jun 6, 2016 at 11:46 AM Luis Henrique B. Sousa <lshsousa@gmail.com> > wrote:

Thanks Vladimir,

The correct link is this one (with the additional min/max operations in
the implementation):

https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

Here is the pull request on the swift-evolution repo:
https://github.com/apple/swift-evolution/pull/328

Any help or suggestion to improve the proposal is welcome. :slight_smile:

- Luis

On Mon, Jun 6, 2016 at 6:10 PM, Vladimir.S via swift-evolution < >> swift-evolution@swift.org> wrote:

Please find this draft of proposal(hope this is correct link for latest
version):

https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

The main idea is to introduce 2 new subscript methods: [clamping:] and
[checking:]

There was discussion in "[Proposal] More lenient subscript methods over
Collections" and (older) "[Proposal] Safer half-open range operator"

On 06.06.2016 19:50, Rob Norback via swift-evolution wrote:

Hi Everyone!

This is my first time emailing the swift evolution list, so if this
topic
has already been discussed please let me know. I looked through all the
accepted and rejected proposals and it doesn't seem to be on there.

The main thought is that dictionaries return optionals, so why not
arrays?
Or other CollectionTypes for that matter. I would think this would be
the
expected behavior in this situation:

var myArray:[String?] = []
print(myArray[4])
// EXC_BAD_INSTRUCTION, but could just be Optional(nil)

Then you could do things like

if let arrayValue = myArray[4] {
   // do something
}

Of course you could simply check with with the count, but considering
Swift's use of optionals to represent empty variables rather than
erroring
out or returning an empty String, I think this functionality would be
appropriate to include in the Swift standard library.

And there's about 15,000 people who've looked for this functionality in
the
last year:

http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings
.

Please let me know what you think.

Best,
Rob Norback

_______________________________________________
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


(Luis Henrique Borges) #7

Thanks Vladimir,

The correct link is this one (with the additional min/max operations in the
implementation):
https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

Here is the pull request on the swift-evolution repo:
https://github.com/apple/swift-evolution/pull/328

Any help or suggestion to improve the proposal is welcome. :slight_smile:

- Luis

···

On Mon, Jun 6, 2016 at 6:10 PM, Vladimir.S via swift-evolution < swift-evolution@swift.org> wrote:

Please find this draft of proposal(hope this is correct link for latest
version):

https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

The main idea is to introduce 2 new subscript methods: [clamping:] and
[checking:]

There was discussion in "[Proposal] More lenient subscript methods over
Collections" and (older) "[Proposal] Safer half-open range operator"

On 06.06.2016 19:50, Rob Norback via swift-evolution wrote:

Hi Everyone!

This is my first time emailing the swift evolution list, so if this topic
has already been discussed please let me know. I looked through all the
accepted and rejected proposals and it doesn't seem to be on there.

The main thought is that dictionaries return optionals, so why not arrays?
Or other CollectionTypes for that matter. I would think this would be the
expected behavior in this situation:

var myArray:[String?] = []
print(myArray[4])
// EXC_BAD_INSTRUCTION, but could just be Optional(nil)

Then you could do things like

if let arrayValue = myArray[4] {
   // do something
}

Of course you could simply check with with the count, but considering
Swift's use of optionals to represent empty variables rather than erroring
out or returning an empty String, I think this functionality would be
appropriate to include in the Swift standard library.

And there's about 15,000 people who've looked for this functionality in
the
last year:

http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings
.

Please let me know what you think.

Best,
Rob Norback

_______________________________________________
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


(Luis Henrique Borges) #8

Yes, Rob, even though our proposals are very related, I do think that yours
would fit better in a new proposal.

My first draft was also in regards to change the default behaviour - not
focused on optionals though. It went through a discussion about *masking*
the current fail fast behaviour (e.g. debugging would be more difficult,
could lead to some unexpected bugs, etc) so that we have changed it to
propose those additional subscript methods instead.

On the other hand, your proposal seems to be more consistent with the
existing *problem* and I think it should follow the path I had tried
initially, and hopefully it will get accepted. Considering my python/ruby
background, I really think we need more handy and lenient operations over
collections.

Let's keep the discussion going, but so far I am +1 for that initial idea.

- Luis

···

On Mon, Jun 6, 2016 at 7:02 PM, Rob Norback <rnorback@gmail.com> wrote:

First of all, thank you all for bringing me up to date so quickly. I
looked over the proposal and it looks awesome.

But as Chris mentioned, this doesn't solve the expected behavior and
ambiguity of ```Array<Int?>```

In this case I would expect the default behavior (myArray[4]) without
using myArray[checking: 4] should return a nil in this case.

And Chris, I think it would make the most sense to have myArray[0] = nil
to be stored if the index is in Range, and for myArray[100] = nil to give a
warning of no assignment being made because index is out of range, kind of
like an unused variable. Right now myArray[100] = nil gives you
EXC_BAD_INSTRUCTION. Then if you assigned myArray[100] = 200, that would
have to simply change the Range.

Chris, I honestly have to think more about that ambiguity with
dictionaries.

I can see that this would definitely need some further fleshing out, but
it seems to be sufficiently different from Luis' proposal to perhaps merit
it's own proposal.

It's up to you Luis, but I think this might be a bit more controversial
then the changes you've proposed, making it possible for your proposal
getting rejected. (I want your proposal accepted, since I would use those
features today). Partial acceptance of a proposal doesn't seem to be a
thing. (Once again please correct me if I'm wrong).

On Mon, Jun 6, 2016 at 11:46 AM Luis Henrique B. Sousa <lshsousa@gmail.com> > wrote:

Thanks Vladimir,

The correct link is this one (with the additional min/max operations in
the implementation):

https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

Here is the pull request on the swift-evolution repo:
https://github.com/apple/swift-evolution/pull/328

Any help or suggestion to improve the proposal is welcome. :slight_smile:

- Luis

On Mon, Jun 6, 2016 at 6:10 PM, Vladimir.S via swift-evolution < >> swift-evolution@swift.org> wrote:

Please find this draft of proposal(hope this is correct link for latest
version):

https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

The main idea is to introduce 2 new subscript methods: [clamping:] and
[checking:]

There was discussion in "[Proposal] More lenient subscript methods over
Collections" and (older) "[Proposal] Safer half-open range operator"

On 06.06.2016 19:50, Rob Norback via swift-evolution wrote:

Hi Everyone!

This is my first time emailing the swift evolution list, so if this
topic
has already been discussed please let me know. I looked through all the
accepted and rejected proposals and it doesn't seem to be on there.

The main thought is that dictionaries return optionals, so why not
arrays?
Or other CollectionTypes for that matter. I would think this would be
the
expected behavior in this situation:

var myArray:[String?] = []
print(myArray[4])
// EXC_BAD_INSTRUCTION, but could just be Optional(nil)

Then you could do things like

if let arrayValue = myArray[4] {
   // do something
}

Of course you could simply check with with the count, but considering
Swift's use of optionals to represent empty variables rather than
erroring
out or returning an empty String, I think this functionality would be
appropriate to include in the Swift standard library.

And there's about 15,000 people who've looked for this functionality in
the
last year:

http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings
.

Please let me know what you think.

Best,
Rob Norback

_______________________________________________
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


(Vladimir) #9

First of all, thank you all for bringing me up to date so quickly. I
looked over the proposal and it looks awesome.

But as Chris mentioned, this doesn't solve the expected behavior and
ambiguity of ```Array<Int?>```

In this case I would expect the default behavior (myArray[4]) without using
myArray[checking: 4] should return a nil in this case.

As Luis already noted, there was a discussion started with exactly the same suggestion : return optional for wrong index/range. During the discussion consensus was(I believe so) found that such proposal could not be supported. But, as an alternative, special explicit syntax for optional/checking results for index/range parameter was suggested. I'd recommend to read messages of these discussions.

As for [Int?], I believe we need no any additional solution for this special case: you have to check if index is in array's bounds and if it is, get value using standard subscript method.

···

On 06.06.2016 21:02, Rob Norback wrote:

And Chris, I think it would make the most sense to have myArray[0] = nil to
be stored if the index is in Range, and for myArray[100] = nil to give a
warning of no assignment being made because index is out of range, kind of
like an unused variable. Right now myArray[100] = nil gives you
EXC_BAD_INSTRUCTION. Then if you assigned myArray[100] = 200, that would
have to simply change the Range.

Chris, I honestly have to think more about that ambiguity with dictionaries.

I can see that this would definitely need some further fleshing out, but it
seems to be sufficiently different from Luis' proposal to perhaps merit
it's own proposal.

It's up to you Luis, but I think this might be a bit more controversial
then the changes you've proposed, making it possible for your proposal
getting rejected. (I want your proposal accepted, since I would use those
features today). Partial acceptance of a proposal doesn't seem to be a
thing. (Once again please correct me if I'm wrong).

On Mon, Jun 6, 2016 at 11:46 AM Luis Henrique B. Sousa <lshsousa@gmail.com > <mailto:lshsousa@gmail.com>> wrote:

    Thanks Vladimir,

    The correct link is this one (with the additional min/max operations in
    the implementation):
    https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

    Here is the pull request on the swift-evolution
    repo: https://github.com/apple/swift-evolution/pull/328

    Any help or suggestion to improve the proposal is welcome. :slight_smile:

    - Luis

    On Mon, Jun 6, 2016 at 6:10 PM, Vladimir.S via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

        Please find this draft of proposal(hope this is correct link for
        latest version):
        https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

        The main idea is to introduce 2 new subscript methods: [clamping:]
        and [checking:]

        There was discussion in "[Proposal] More lenient subscript methods
        over Collections" and (older) "[Proposal] Safer half-open range
        operator"

        On 06.06.2016 19:50, Rob Norback via swift-evolution wrote:

            Hi Everyone!

            This is my first time emailing the swift evolution list, so if
            this topic
            has already been discussed please let me know. I looked
            through all the
            accepted and rejected proposals and it doesn't seem to be on there.

            The main thought is that dictionaries return optionals, so why
            not arrays?
            Or other CollectionTypes for that matter. I would think this
            would be the
            expected behavior in this situation:

            var myArray:[String?] = []
            print(myArray[4])
            // EXC_BAD_INSTRUCTION, but could just be Optional(nil)

            Then you could do things like

            if let arrayValue = myArray[4] {
               // do something
            }

            Of course you could simply check with with the count, but
            considering
            Swift's use of optionals to represent empty variables rather
            than erroring
            out or returning an empty String, I think this functionality
            would be
            appropriate to include in the Swift standard library.

            And there's about 15,000 people who've looked for this
            functionality in the
            last year:
            http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings.

            Please let me know what you think.

            Best,
            Rob Norback

            _______________________________________________
            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


(Rob Norback) #10

Vladimir, thank you for pointing me to the discussion again. I read through the entire thing. And I didn't see a consensus around [Int?].

The main argument against was that it would allow the developer to be clumsy and remain unaware of a problem in the code because the choice is not explicit enough.

The main argument for is that dictionaries already do this, so why don't we have to explicitly check if a dictionary key is within bounds?

IMO casting an array to [Int?] is an explicit choice. One I would expect to always return an optional from a subscript. A [Int] array should still fail fast.

I'd like to clearly understand the downside of swift behaving this way, and why a proposal like this would not be supported. Not to be confrontational, but simply to expand my own perspective. Perhaps some more explicit examples of developer laziness that could cause major problems. I find I always have to be much more careful when coding with optionals.

···

On Jun 7, 2016, at 5:48 AM, Vladimir.S <svabox@gmail.com> wrote:

On 06.06.2016 21:02, Rob Norback wrote:
First of all, thank you all for bringing me up to date so quickly. I
looked over the proposal and it looks awesome.

But as Chris mentioned, this doesn't solve the expected behavior and
ambiguity of ```Array<Int?>```

In this case I would expect the default behavior (myArray[4]) without using
myArray[checking: 4] should return a nil in this case.

As Luis already noted, there was a discussion started with exactly the same suggestion : return optional for wrong index/range. During the discussion consensus was(I believe so) found that such proposal could not be supported. But, as an alternative, special explicit syntax for optional/checking results for index/range parameter was suggested. I'd recommend to read messages of these discussions.

As for [Int?], I believe we need no any additional solution for this special case: you have to check if index is in array's bounds and if it is, get value using standard subscript method.

And Chris, I think it would make the most sense to have myArray[0] = nil to
be stored if the index is in Range, and for myArray[100] = nil to give a
warning of no assignment being made because index is out of range, kind of
like an unused variable. Right now myArray[100] = nil gives you
EXC_BAD_INSTRUCTION. Then if you assigned myArray[100] = 200, that would
have to simply change the Range.

Chris, I honestly have to think more about that ambiguity with dictionaries.

I can see that this would definitely need some further fleshing out, but it
seems to be sufficiently different from Luis' proposal to perhaps merit
it's own proposal.

It's up to you Luis, but I think this might be a bit more controversial
then the changes you've proposed, making it possible for your proposal
getting rejected. (I want your proposal accepted, since I would use those
features today). Partial acceptance of a proposal doesn't seem to be a
thing. (Once again please correct me if I'm wrong).

On Mon, Jun 6, 2016 at 11:46 AM Luis Henrique B. Sousa <lshsousa@gmail.com >> <mailto:lshsousa@gmail.com>> wrote:

   Thanks Vladimir,

   The correct link is this one (with the additional min/max operations in
   the implementation):
   https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

   Here is the pull request on the swift-evolution
   repo: https://github.com/apple/swift-evolution/pull/328

   Any help or suggestion to improve the proposal is welcome. :slight_smile:

   - Luis

   On Mon, Jun 6, 2016 at 6:10 PM, Vladimir.S via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

       Please find this draft of proposal(hope this is correct link for
       latest version):
       https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

       The main idea is to introduce 2 new subscript methods: [clamping:]
       and [checking:]

       There was discussion in "[Proposal] More lenient subscript methods
       over Collections" and (older) "[Proposal] Safer half-open range
       operator"

       On 06.06.2016 19:50, Rob Norback via swift-evolution wrote:

           Hi Everyone!

           This is my first time emailing the swift evolution list, so if
           this topic
           has already been discussed please let me know. I looked
           through all the
           accepted and rejected proposals and it doesn't seem to be on there.

           The main thought is that dictionaries return optionals, so why
           not arrays?
           Or other CollectionTypes for that matter. I would think this
           would be the
           expected behavior in this situation:

           var myArray:[String?] = []
           print(myArray[4])
           // EXC_BAD_INSTRUCTION, but could just be Optional(nil)

           Then you could do things like

           if let arrayValue = myArray[4] {
              // do something
           }

           Of course you could simply check with with the count, but
           considering
           Swift's use of optionals to represent empty variables rather
           than erroring
           out or returning an empty String, I think this functionality
           would be
           appropriate to include in the Swift standard library.

           And there's about 15,000 people who've looked for this
           functionality in the
           last year:
           http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings.

           Please let me know what you think.

           Best,
           Rob Norback

           _______________________________________________
           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


(Vladimir) #11

It seems like you are mixing two proposals: optional result of non-optional array and return value of optional array.

I'm commenting the first - as it was already discussed earlier and based on community reaction on it - I believe it will not be supported again. Array is expected to fail fast when we access with wrong index.
But let's hear other opinions, may be I'm wrong.

As for second proposal/problem with [Int?] - I don't remember such discussion, so probably you should create a separate thread for it. It seems like I don't understand the problem with [Int?] in details, so have no opinion right now. IMO dictionary [Type1:Type2?] is a special case where you need to use myDict.keys.contains(keyValue) first to determinate if you have a value for key and after this you can get the value itself(which is Optional).

···

On 07.06.2016 16:42, Rob Norback wrote:

Vladimir, thank you for pointing me to the discussion again. I read through the entire thing. And I didn't see a consensus around [Int?].

The main argument against was that it would allow the developer to be clumsy and remain unaware of a problem in the code because the choice is not explicit enough.

The main argument for is that dictionaries already do this, so why don't we have to explicitly check if a dictionary key is within bounds?

IMO casting an array to [Int?] is an explicit choice. One I would expect to always return an optional from a subscript. A [Int] array should still fail fast.

I'd like to clearly understand the downside of swift behaving this way, and why a proposal like this would not be supported. Not to be confrontational, but simply to expand my own perspective. Perhaps some more explicit examples of developer laziness that could cause major problems. I find I always have to be much more careful when coding with optionals.

On Jun 7, 2016, at 5:48 AM, Vladimir.S <svabox@gmail.com> wrote:

On 06.06.2016 21:02, Rob Norback wrote:
First of all, thank you all for bringing me up to date so quickly. I
looked over the proposal and it looks awesome.

But as Chris mentioned, this doesn't solve the expected behavior and
ambiguity of ```Array<Int?>```

In this case I would expect the default behavior (myArray[4]) without using
myArray[checking: 4] should return a nil in this case.

As Luis already noted, there was a discussion started with exactly the same suggestion : return optional for wrong index/range. During the discussion consensus was(I believe so) found that such proposal could not be supported. But, as an alternative, special explicit syntax for optional/checking results for index/range parameter was suggested. I'd recommend to read messages of these discussions.

As for [Int?], I believe we need no any additional solution for this special case: you have to check if index is in array's bounds and if it is, get value using standard subscript method.

And Chris, I think it would make the most sense to have myArray[0] = nil to
be stored if the index is in Range, and for myArray[100] = nil to give a
warning of no assignment being made because index is out of range, kind of
like an unused variable. Right now myArray[100] = nil gives you
EXC_BAD_INSTRUCTION. Then if you assigned myArray[100] = 200, that would
have to simply change the Range.

Chris, I honestly have to think more about that ambiguity with dictionaries.

I can see that this would definitely need some further fleshing out, but it
seems to be sufficiently different from Luis' proposal to perhaps merit
it's own proposal.

It's up to you Luis, but I think this might be a bit more controversial
then the changes you've proposed, making it possible for your proposal
getting rejected. (I want your proposal accepted, since I would use those
features today). Partial acceptance of a proposal doesn't seem to be a
thing. (Once again please correct me if I'm wrong).

On Mon, Jun 6, 2016 at 11:46 AM Luis Henrique B. Sousa <lshsousa@gmail.com >>> <mailto:lshsousa@gmail.com>> wrote:

   Thanks Vladimir,

   The correct link is this one (with the additional min/max operations in
   the implementation):
   https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

   Here is the pull request on the swift-evolution
   repo: https://github.com/apple/swift-evolution/pull/328

   Any help or suggestion to improve the proposal is welcome. :slight_smile:

   - Luis

   On Mon, Jun 6, 2016 at 6:10 PM, Vladimir.S via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

       Please find this draft of proposal(hope this is correct link for
       latest version):
       https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

       The main idea is to introduce 2 new subscript methods: [clamping:]
       and [checking:]

       There was discussion in "[Proposal] More lenient subscript methods
       over Collections" and (older) "[Proposal] Safer half-open range
       operator"

       On 06.06.2016 19:50, Rob Norback via swift-evolution wrote:

           Hi Everyone!

           This is my first time emailing the swift evolution list, so if
           this topic
           has already been discussed please let me know. I looked
           through all the
           accepted and rejected proposals and it doesn't seem to be on there.

           The main thought is that dictionaries return optionals, so why
           not arrays?
           Or other CollectionTypes for that matter. I would think this
           would be the
           expected behavior in this situation:

           var myArray:[String?] = []
           print(myArray[4])
           // EXC_BAD_INSTRUCTION, but could just be Optional(nil)

           Then you could do things like

           if let arrayValue = myArray[4] {
              // do something
           }

           Of course you could simply check with with the count, but
           considering
           Swift's use of optionals to represent empty variables rather
           than erroring
           out or returning an empty String, I think this functionality
           would be
           appropriate to include in the Swift standard library.

           And there's about 15,000 people who've looked for this
           functionality in the
           last year:
           http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings.

           Please let me know what you think.

           Best,
           Rob Norback

           _______________________________________________
           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


(Rob Norback) #12

I think you're right Vladimir. After having this discussion I've changed my opinion on normal arrays returning optionals. I don't think that's a good idea as its not explicit and is unexpected behavior.

I'd simply like to draft a proposal that has arrays of optionals returning optionals for all indicies with no 'Index out of bounds errors' as I think it's explicit [Int?] and closer to expected behavior.

I'd need to flesh out how assignment would behave differently for an array of optionals since assigning a value out of bounds would likely have a different expected effect as well.

···

On Jun 7, 2016, at 8:33 AM, Vladimir.S <svabox@gmail.com> wrote:

It seems like you are mixing two proposals: optional result of non-optional array and return value of optional array.

I'm commenting the first - as it was already discussed earlier and based on community reaction on it - I believe it will not be supported again. Array is expected to fail fast when we access with wrong index.
But let's hear other opinions, may be I'm wrong.

As for second proposal/problem with [Int?] - I don't remember such discussion, so probably you should create a separate thread for it. It seems like I don't understand the problem with [Int?] in details, so have no opinion right now. IMO dictionary [Type1:Type2?] is a special case where you need to use myDict.keys.contains(keyValue) first to determinate if you have a value for key and after this you can get the value itself(which is Optional).

On 07.06.2016 16:42, Rob Norback wrote:
Vladimir, thank you for pointing me to the discussion again. I read through the entire thing. And I didn't see a consensus around [Int?].

The main argument against was that it would allow the developer to be clumsy and remain unaware of a problem in the code because the choice is not explicit enough.

The main argument for is that dictionaries already do this, so why don't we have to explicitly check if a dictionary key is within bounds?

IMO casting an array to [Int?] is an explicit choice. One I would expect to always return an optional from a subscript. A [Int] array should still fail fast.

I'd like to clearly understand the downside of swift behaving this way, and why a proposal like this would not be supported. Not to be confrontational, but simply to expand my own perspective. Perhaps some more explicit examples of developer laziness that could cause major problems. I find I always have to be much more careful when coding with optionals.

On Jun 7, 2016, at 5:48 AM, Vladimir.S <svabox@gmail.com> wrote:

On 06.06.2016 21:02, Rob Norback wrote:
First of all, thank you all for bringing me up to date so quickly. I
looked over the proposal and it looks awesome.

But as Chris mentioned, this doesn't solve the expected behavior and
ambiguity of ```Array<Int?>```

In this case I would expect the default behavior (myArray[4]) without using
myArray[checking: 4] should return a nil in this case.

As Luis already noted, there was a discussion started with exactly the same suggestion : return optional for wrong index/range. During the discussion consensus was(I believe so) found that such proposal could not be supported. But, as an alternative, special explicit syntax for optional/checking results for index/range parameter was suggested. I'd recommend to read messages of these discussions.

As for [Int?], I believe we need no any additional solution for this special case: you have to check if index is in array's bounds and if it is, get value using standard subscript method.

And Chris, I think it would make the most sense to have myArray[0] = nil to
be stored if the index is in Range, and for myArray[100] = nil to give a
warning of no assignment being made because index is out of range, kind of
like an unused variable. Right now myArray[100] = nil gives you
EXC_BAD_INSTRUCTION. Then if you assigned myArray[100] = 200, that would
have to simply change the Range.

Chris, I honestly have to think more about that ambiguity with dictionaries.

I can see that this would definitely need some further fleshing out, but it
seems to be sufficiently different from Luis' proposal to perhaps merit
it's own proposal.

It's up to you Luis, but I think this might be a bit more controversial
then the changes you've proposed, making it possible for your proposal
getting rejected. (I want your proposal accepted, since I would use those
features today). Partial acceptance of a proposal doesn't seem to be a
thing. (Once again please correct me if I'm wrong).

On Mon, Jun 6, 2016 at 11:46 AM Luis Henrique B. Sousa <lshsousa@gmail.com >>>> <mailto:lshsousa@gmail.com>> wrote:

  Thanks Vladimir,

  The correct link is this one (with the additional min/max operations in
  the implementation):
  https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

  Here is the pull request on the swift-evolution
  repo: https://github.com/apple/swift-evolution/pull/328

  Any help or suggestion to improve the proposal is welcome. :slight_smile:

  - Luis

  On Mon, Jun 6, 2016 at 6:10 PM, Vladimir.S via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

      Please find this draft of proposal(hope this is correct link for
      latest version):
      https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

      The main idea is to introduce 2 new subscript methods: [clamping:]
      and [checking:]

      There was discussion in "[Proposal] More lenient subscript methods
      over Collections" and (older) "[Proposal] Safer half-open range
      operator"

      On 06.06.2016 19:50, Rob Norback via swift-evolution wrote:

          Hi Everyone!

          This is my first time emailing the swift evolution list, so if
          this topic
          has already been discussed please let me know. I looked
          through all the
          accepted and rejected proposals and it doesn't seem to be on there.

          The main thought is that dictionaries return optionals, so why
          not arrays?
          Or other CollectionTypes for that matter. I would think this
          would be the
          expected behavior in this situation:

          var myArray:[String?] = []
          print(myArray[4])
          // EXC_BAD_INSTRUCTION, but could just be Optional(nil)

          Then you could do things like

          if let arrayValue = myArray[4] {
             // do something
          }

          Of course you could simply check with with the count, but
          considering
          Swift's use of optionals to represent empty variables rather
          than erroring
          out or returning an empty String, I think this functionality
          would be
          appropriate to include in the Swift standard library.

          And there's about 15,000 people who've looked for this
          functionality in the
          last year:
          http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings.

          Please let me know what you think.

          Best,
          Rob Norback

          _______________________________________________
          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


(Jeremy Pereira) #13

IMO dictionary [Type1:Type2?] is a special case where you need to use myDict.keys.contains(keyValue) first to determinate if you have a value for key and after this you can get the value itself(which is Optional).

I don’t understand why you think it is a special case. The return type of subscripting [ T1 : T2?] is T2?? or Optional<Optional<T2>>. You can do all the normal unwrapping you would expect except that one unwrapping results in another optional e.g.

···

---
var sqrt: [Int : Int?] = [ 1: 1, 4 : 2, 2 : nil]

func tellMeTheSquareRoot(n : Int) -> String
{
    if let lookupResult = sqrt[n]
    {
        if let theSquareRoot = lookupResult
        {
            return "\(n) has a square root and it is \(theSquareRoot)"
        }
        else
        {
            return "\(n) has a square root but it is not an integer"
        }
    }
    else
    {
        return "I can't imagine what the square root of \(n) might be"
    }
}

print(tellMeTheSquareRoot(4))
print(tellMeTheSquareRoot(2))
print(tellMeTheSquareRoot(-1))

gives the results

4 has a square root and it is 2
2 has a square root but it is not an integer
I can't imagine what the square root of -1 might be

Comparing to nil is ambiguous to the human eye but the compiler makes a decision

sqrt[2] == nil // false (huh?)
sqrt[-1] == nil // true

The reason the first one is false is because the return result is not nil but

Optional<Optional<Int>>.Some(Optional<Int>.None>)

A similar rule applies to assignment to a subscript, the compiler assumes the “top level” of optional but you can force the addition of an element with a nil value by being explicit.

sqrt[2] = nil // [4: Optional(2), 1: Optional(1)] - 2 has been zapped

sqrt[2] = Optional<Int>.None // [2: nil, 4: Optional(2), 1: Optional(1)] - 2 has been re-added


(Vladimir) #14

Yes, thank you Jeremy for pointing on this, my fault :-(, was confused by initial description of the problem in proposal and in my fast test I got "Optional(nil)" in console for existed "nil" value in dict, but didn't realized that it should be printed just "nil".

···

On 07.06.2016 19:06, Jeremy Pereira wrote:

IMO dictionary [Type1:Type2?] is a special case where you need to use myDict.keys.contains(keyValue) first to determinate if you have a value for key and after this you can get the value itself(which is Optional).

I don’t understand why you think it is a special case. The return type of subscripting [ T1 : T2?] is T2?? or Optional<Optional<T2>>. You can do all the normal unwrapping you would expect except that one unwrapping results in another optional e.g.

---
var sqrt: [Int : Int?] = [ 1: 1, 4 : 2, 2 : nil]

func tellMeTheSquareRoot(n : Int) -> String
{
    if let lookupResult = sqrt[n]
    {
        if let theSquareRoot = lookupResult
        {
            return "\(n) has a square root and it is \(theSquareRoot)"
        }
        else
        {
            return "\(n) has a square root but it is not an integer"
        }
    }
    else
    {
        return "I can't imagine what the square root of \(n) might be"
    }
}

print(tellMeTheSquareRoot(4))
print(tellMeTheSquareRoot(2))
print(tellMeTheSquareRoot(-1))

gives the results

4 has a square root and it is 2
2 has a square root but it is not an integer
I can't imagine what the square root of -1 might be

Comparing to nil is ambiguous to the human eye but the compiler makes a decision

sqrt[2] == nil // false (huh?)
sqrt[-1] == nil // true

The reason the first one is false is because the return result is not nil but

Optional<Optional<Int>>.Some(Optional<Int>.None>)

A similar rule applies to assignment to a subscript, the compiler assumes the “top level” of optional but you can force the addition of an element with a nil value by being explicit.

sqrt[2] = nil // [4: Optional(2), 1: Optional(1)] - 2 has been zapped

sqrt[2] = Optional<Int>.None // [2: nil, 4: Optional(2), 1: Optional(1)] - 2 has been re-added