[Proposal] More lenient subscript methods over Collections (was: [Proposal] Safer half-open range operator)

One point which should be discussed is the following behaviour:

let array = [0]
// ranges are completely out of bounds and produce an error
array[clamping: 1...2] // error
array[clamping: -2...-1] // error

Should a range which has no intersection with the indices of the collection
produce an error or just clamp to 0..<0 respectively endIndex..<endIndex?

I expect it will returns i.e. empty array, as no elements with 1...2(-2..-1) indexes in the array. I understand `clamping` similar as 'bounded','in these bounds'. And as soon as [0,1,2,3,4][clamping:2...10] will silently move the right position to allowed index(4), and [0,1,2,3,4][clamping:-2...0] will move left position to 0, I expect that in [0][clamping: 1...2] will try to move both limits to allowed, and as no intersection - silently return empty array.

···

On 15.05.2016 0:09, Maximilian Hünenberger via swift-evolution wrote:

Best regards
Maximilian

Am 13.05.2016 um 17:10 schrieb Luis Henrique B. Sousa via swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

It seems that there is a consensus that this proposal might be a good
addition to the standard library. All comments on this thread in the past
few weeks were related to naming, not around the behaviour or validity of
the proposed methods. So I will submit this proposal for review very soon
assuming that nobody else has strong arguments against it. :-)

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

If you have any corrections or suggestions to the proposal text itself,
please comment on this gist:
nnnn-more-lenient-collections-subscripts.md · GitHub
(or pull request to my repo)

Regards,

- Luis

On Tue, May 10, 2016 at 4:13 PM, Luis Henrique B. Sousa >> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

    Please let me know if you have more suggestions or corrections on
    this proposal.
    I'm tempted to submit it for review. :-)

    - Luis

    On Tue, May 10, 2016 at 8:53 AM, Luis Henrique B. Sousa >> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

        It sounds good, thanks for you suggestions @Vladimir, @Patrick
        and @Brent.

        I've just updated the proposal:
        https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md#detailed-design

        - Luis

        On Tue, May 10, 2016 at 6:50 AM, Vladimir.S via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

            Yes, I feel like 'within' is much better than 'bounded'.

            How about such changes in proposal:

            a[bounded: -1 ..< 5] --> a[within: -1 ..< 5] (or a[inside:
            -1 ..< 5] )

            a[optional: 0 ..< 5] --> a[checking: 0 ..< 5]
            a[optional: 5] --> a[checking: 5]

            ?

            On 10.05.2016 6:27, Patrick Smith via swift-evolution wrote:

                I like the idea of the of the bounded subscript, however
                the optional one I
                feel could be used for clumsy code.

                .first and .last have value, but once you start stepping
                several arbitrary
                indices in, then that code is likely fragile?

                I can think of ‘within’, ‘inside’ and ‘intersecting’ as
                alternative names
                for ‘bounded’ that attempt to explain what is going on:

                let a = [1, 2, 3]

                a[within: 0 ..< 5] // [1, 2, 3]
                a[inside: 0 ..< 5] // [1, 2, 3]
                a[intersecting: 0 ..< 5] // [1, 2, 3]

                    On 28 Apr 2016, at 10:11 PM, Luis Henrique B. Sousa
                    via swift-evolution
                    <swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto:swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>>> wrote:

                    As we have discussed throughout this thread, the
                    initial proposal was
                    modified to include alternative subscript methods
                    instead of modifying
                    the default operator/subscript behaviour.
                    The first draft is
                    here:
                    https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

                    I've also put this as a gist so that you can leave
                    comments with respect
                    to the proposal document itself. Any suggestion or
                    help is very welcome.
                    nnnn-more-lenient-collections-subscripts.md · GitHub

                    Regards,

                    - Luis

                    On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B. Sousa >> <lshsousa@gmail.com <mailto:lshsousa@gmail.com> >> <mailto:lshsousa@gmail.com >> <mailto:lshsousa@gmail.com>>> wrote:

                        This proposal seeks to provide a safer ..< (aka
                    half-open range
                        operator) in order to avoid **Array index out of
                    range** errors in
                        execution time.

                        Here is my first draft for this proposal:

                    https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md

                        In short, doing that in Swift causes a runtime error:

                        leta =[1,2,3]
                        letb =a[0..<5]
                        print(b)

                        > Error running code:
                        > fatal error: Array index out of range

                        The proposed solution is to slice the array
                    returning all elements
                        that are below the half-open operator, even
                    though the number of
                        elements is lesser than the ending of the
                    half-open operator. So the
                        example above would return [1,2,3].
                        We can see this very behaviour in other
                    languages, such as Python and
                        Ruby as shown in the proposal draft.

                        This would eliminate the need for verifications
                    on the array size
                        before slicing it -- and consequently runtime
                    errors in cases when
                        the programmer didn't.

                        Viewing that it is my very first proposal, any
                    feedback will be helpful.

                        Thanks!

                        Luis Henrique Borges
                        @luishborges

                    _______________________________________________
                    swift-evolution mailing list
                    swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto: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 <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

Did you consider making the safer, optional overload the "default" and just omit the label?

···

Sent from my iPad

On May 6, 2016, at 10:23 AM, Luis Henrique B. Sousa via swift-evolution <swift-evolution@swift.org> wrote:

"bounded" sounds good to me, but I don't know if "optional" is a good choice as it could be highlighted as a reserved keyword:

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

- Luis

On Fri, Apr 29, 2016 at 5:08 PM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:
From my point of view,
truncate -> bounded
lenient -> keep "lenient:" ? "requested:" ? "optional:"?

On 29.04.2016 17:46, Thorsten Seitz wrote:
Some alternatives to 'safe:'

existing:
bounded:
valid:

-Thorsten

Am 29.04.2016 um 00:20 schrieb Luis Henrique B. Sousa via swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Thanks Vladimir, your considerations and suggestions are totally valid,
I'm going to change the document accordingly.
Also as a non-native English speaker I think that other words could fit
better, such as 'tolerant' or 'permissive' -- but I dunno if they would
look great as a label. We will come up with the right keyword for it.

In relation to bad code, it could be a valid argument if my initial
proposal was under discussion instead, where the default 'fail fast'
behaviour would be "camouflaged" and bugs would be more difficult to
catch. In this new proposal we have such features explicitly defined,
where the user will be familiar with what it does and what results to
expect for. I don't see a way that it could drive to bad written code.

- Luis

On Thu, Apr 28, 2016 at 2:37 PM, Vladimir.S <svabox@gmail.com >>>> <mailto:svabox@gmail.com>> wrote:

    I support this proposal. Probably we all should select the best
    labels (truncate/lenient or other). As not native English speaker, I
    don't feel like 'lenient' is well-known word or often-used word in
    software development. But all this just a details we need to discuss.

    What I think could be improved - is a motivation section. IMO the
    main purpose of proposed features is not to "eliminate the need for
    validations, reduce the number of fatal errors in runtime" but to
    allow us to have more clean code when *such validations just don't
    required*, when we just *don't care* about details.
    I.e. in situations, when we'll use [max(-1, a.startIndex) ..< min(5,
    a.endIndex)] and bounds checking manually to have the same result as
    in proposed subscripts.

    I.e. it is just a very handy addition to standard methods for
    collections, just like we can get first element by index but we have
    handy property '.first' for this purpose. Btw, it does not raise
    error, but returns T?. I think you can add notes regarding analogues
    with .first / .last properties(and probably with other) in proposal text.

    Someone can argue, that by using these subscripts, coders can write
    'bad' code - but I can't accept such an argument - 'bad' coders
    already can write 'bad' code with other features of Swift and at the
    end they can implement these subscripts in their project and write
    'bad' code. Should we stop to introduce handy and explicit feature
    for 'good' coders because of this?

    On 28.04.2016 15:11, Luis Henrique B. Sousa via swift-evolution wrote:

        As we have discussed throughout this thread, the initial proposal was
        modified to include alternative subscript methods instead of
        modifying the
        default operator/subscript behaviour.
        The first draft is
        here:
        https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

        I've also put this as a gist so that you can leave comments with
        respect to
        the proposal document itself. Any suggestion or help is very welcome.
        nnnn-more-lenient-collections-subscripts.md · GitHub

        Regards,

        - Luis

        On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B. Sousa >>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com> >>>> <mailto:lshsousa@gmail.com <mailto:lshsousa@gmail.com>>> wrote:

            This proposal seeks to provide a safer ..< (aka half-open range
            operator) in order to avoid **Array index out of range**
        errors in
            execution time.

            Here is my first draft for this proposal:

        https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md

            In short, doing that in Swift causes a runtime error:

            leta =[1,2,3]
            letb =a[0..<5]
            print(b)

            > Error running code:
            > fatal error: Array index out of range

            The proposed solution is to slice the array returning all
        elements that
            are below the half-open operator, even though the number of
        elements is
            lesser than the ending of the half-open operator. So the
        example above
            would return [1,2,3].
            We can see this very behaviour in other languages, such as
        Python and
            Ruby as shown in the proposal draft.

            This would eliminate the need for verifications on the array size
            before slicing it -- and consequently runtime errors in cases
        when the
            programmer didn't.

            Viewing that it is my very first proposal, any feedback will
        be helpful.

            Thanks!

            Luis Henrique Borges
            @luishborges

        _______________________________________________
        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

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

Yes @Matthew, I did; my very first draft sought to change the default
subscript method. However, there were some opinions against overriding the
default *fail fast* behaviour as it could result in more bugs and in an
overload to debug. It wasn't set in stone, so I think it's something that
could be discussed if this proposal goes to review.

- Luis

···

On Fri, May 6, 2016 at 5:22 PM, Matthew Johnson <matthew@anandabits.com> wrote:

Did you consider making the safer, optional overload the "default" and
just omit the label?

Sent from my iPad

On May 6, 2016, at 10:23 AM, Luis Henrique B. Sousa via swift-evolution < > swift-evolution@swift.org> wrote:

"bounded" sounds good to me, but I don't know if "optional" is a good
choice as it could be highlighted as a reserved keyword:

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

- Luis

On Fri, Apr 29, 2016 at 5:08 PM, Vladimir.S via swift-evolution < > swift-evolution@swift.org> wrote:

From my point of view,
truncate -> bounded
lenient -> keep "lenient:" ? "requested:" ? "optional:"?

On 29.04.2016 17:46, Thorsten Seitz wrote:

Some alternatives to 'safe:'

existing:
bounded:
valid:

-Thorsten

Am 29.04.2016 um 00:20 schrieb Luis Henrique B. Sousa via swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Thanks Vladimir, your considerations and suggestions are totally valid,

I'm going to change the document accordingly.
Also as a non-native English speaker I think that other words could fit
better, such as 'tolerant' or 'permissive' -- but I dunno if they would
look great as a label. We will come up with the right keyword for it.

In relation to bad code, it could be a valid argument if my initial
proposal was under discussion instead, where the default 'fail fast'
behaviour would be "camouflaged" and bugs would be more difficult to
catch. In this new proposal we have such features explicitly defined,
where the user will be familiar with what it does and what results to
expect for. I don't see a way that it could drive to bad written code.

- Luis

On Thu, Apr 28, 2016 at 2:37 PM, Vladimir.S <svabox@gmail.com >>>> <mailto:svabox@gmail.com>> wrote:

    I support this proposal. Probably we all should select the best
    labels (truncate/lenient or other). As not native English speaker, I
    don't feel like 'lenient' is well-known word or often-used word in
    software development. But all this just a details we need to
discuss.

    What I think could be improved - is a motivation section. IMO the
    main purpose of proposed features is not to "eliminate the need for
    validations, reduce the number of fatal errors in runtime" but to
    allow us to have more clean code when *such validations just don't
    required*, when we just *don't care* about details.
    I.e. in situations, when we'll use [max(-1, a.startIndex) ..< min(5,
    a.endIndex)] and bounds checking manually to have the same result as
    in proposed subscripts.

    I.e. it is just a very handy addition to standard methods for
    collections, just like we can get first element by index but we have
    handy property '.first' for this purpose. Btw, it does not raise
    error, but returns T?. I think you can add notes regarding analogues
    with .first / .last properties(and probably with other) in proposal
text.

    Someone can argue, that by using these subscripts, coders can write
    'bad' code - but I can't accept such an argument - 'bad' coders
    already can write 'bad' code with other features of Swift and at the
    end they can implement these subscripts in their project and write
    'bad' code. Should we stop to introduce handy and explicit feature
    for 'good' coders because of this?

    On 28.04.2016 15:11, Luis Henrique B. Sousa via swift-evolution >>>> wrote:

        As we have discussed throughout this thread, the initial
proposal was
        modified to include alternative subscript methods instead of
        modifying the
        default operator/subscript behaviour.
        The first draft is
        here:

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

        I've also put this as a gist so that you can leave comments with
        respect to
        the proposal document itself. Any suggestion or help is very
welcome.
        nnnn-more-lenient-collections-subscripts.md · GitHub

        Regards,

        - Luis

        On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B. Sousa >>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com> >>>> <mailto:lshsousa@gmail.com <mailto:lshsousa@gmail.com>>> wrote:

            This proposal seeks to provide a safer ..< (aka half-open
range
            operator) in order to avoid **Array index out of range**
        errors in
            execution time.

            Here is my first draft for this proposal:

https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md

            In short, doing that in Swift causes a runtime error:

            leta =[1,2,3]
            letb =a[0..<5]
            print(b)

            > Error running code:
            > fatal error: Array index out of range

            The proposed solution is to slice the array returning all
        elements that
            are below the half-open operator, even though the number of
        elements is
            lesser than the ending of the half-open operator. So the
        example above
            would return [1,2,3].
            We can see this very behaviour in other languages, such as
        Python and
            Ruby as shown in the proposal draft.

            This would eliminate the need for verifications on the
array size
            before slicing it -- and consequently runtime errors in
cases
        when the
            programmer didn't.

            Viewing that it is my very first proposal, any feedback will
        be helpful.

            Thanks!

            Luis Henrique Borges
            @luishborges

        _______________________________________________
        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

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

Sounds good for me.

How about:

a[bounded: -1 ..< 5] --> a[within: -1 ..< 5] (or a[inside: -1 ..< 5] )

a[optional: 0 ..< 5] --> a[checking: 0 ..< 5]
a[optional: 5] --> a[checking: 5]

?

···

On 10.05.2016 4:29, Brent Royal-Gordon wrote:

lenient -> keep "lenient:" ? "requested:" ? "optional:"?

`checking:`, to indicate that the index will be checked before it's used?

Exactly, the idea is to return an empty array just like other languages do.
(e.g. python)

- Luis

···

On Sun, May 15, 2016 at 10:13 AM, Vladimir.S via swift-evolution < swift-evolution@swift.org> wrote:

On 15.05.2016 0:09, Maximilian Hünenberger via swift-evolution wrote:

One point which should be discussed is the following behaviour:

let array = [0]
// ranges are completely out of bounds and produce an error
array[clamping: 1...2] // error
array[clamping: -2...-1] // error

Should a range which has no intersection with the indices of the
collection
produce an error or just clamp to 0..<0 respectively endIndex..<endIndex?

I expect it will returns i.e. empty array, as no elements with
1...2(-2..-1) indexes in the array. I understand `clamping` similar as
'bounded','in these bounds'. And as soon as [0,1,2,3,4][clamping:2...10]
will silently move the right position to allowed index(4), and
[0,1,2,3,4][clamping:-2...0] will move left position to 0, I expect that
in [0][clamping: 1...2] will try to move both limits to allowed, and as no
intersection - silently return empty array.

Best regards
Maximilian

Am 13.05.2016 um 17:10 schrieb Luis Henrique B. Sousa via swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

It seems that there is a consensus that this proposal might be a good

addition to the standard library. All comments on this thread in the past
few weeks were related to naming, not around the behaviour or validity of
the proposed methods. So I will submit this proposal for review very soon
assuming that nobody else has strong arguments against it. :-)

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

If you have any corrections or suggestions to the proposal text itself,
please comment on this gist:
nnnn-more-lenient-collections-subscripts.md · GitHub
(or pull request to my repo)

Regards,

- Luis

On Tue, May 10, 2016 at 4:13 PM, Luis Henrique B. Sousa >>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

    Please let me know if you have more suggestions or corrections on
    this proposal.
    I'm tempted to submit it for review. :-)

    - Luis

    On Tue, May 10, 2016 at 8:53 AM, Luis Henrique B. Sousa >>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

        It sounds good, thanks for you suggestions @Vladimir, @Patrick
        and @Brent.

        I've just updated the proposal:

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

        - Luis

        On Tue, May 10, 2016 at 6:50 AM, Vladimir.S via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> >>> wrote:

            Yes, I feel like 'within' is much better than 'bounded'.

            How about such changes in proposal:

            a[bounded: -1 ..< 5] --> a[within: -1 ..< 5] (or a[inside:
            -1 ..< 5] )

            a[optional: 0 ..< 5] --> a[checking: 0 ..< 5]
            a[optional: 5] --> a[checking: 5]

            ?

            On 10.05.2016 6:27, Patrick Smith via swift-evolution wrote:

                I like the idea of the of the bounded subscript, however
                the optional one I
                feel could be used for clumsy code.

                .first and .last have value, but once you start stepping
                several arbitrary
                indices in, then that code is likely fragile?

                I can think of ‘within’, ‘inside’ and ‘intersecting’ as
                alternative names
                for ‘bounded’ that attempt to explain what is going on:

                let a = [1, 2, 3]

                a[within: 0 ..< 5] // [1, 2, 3]
                a[inside: 0 ..< 5] // [1, 2, 3]
                a[intersecting: 0 ..< 5] // [1, 2, 3]

                    On 28 Apr 2016, at 10:11 PM, Luis Henrique B. Sousa
                    via swift-evolution
                    <swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto:swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>>> wrote:

                    As we have discussed throughout this thread, the
                    initial proposal was
                    modified to include alternative subscript methods
                    instead of modifying
                    the default operator/subscript behaviour.
                    The first draft is
                    here:

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

                    I've also put this as a gist so that you can leave
                    comments with respect
                    to the proposal document itself. Any suggestion or
                    help is very welcome.

nnnn-more-lenient-collections-subscripts.md · GitHub

                    Regards,

                    - Luis

                    On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B.
Sousa
                    <lshsousa@gmail.com <mailto:lshsousa@gmail.com>
                    <mailto:lshsousa@gmail.com

                    <mailto:lshsousa@gmail.com>>> wrote:

                        This proposal seeks to provide a safer ..< (aka
                    half-open range
                        operator) in order to avoid **Array index out of
                    range** errors in
                        execution time.

                        Here is my first draft for this proposal:

https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md

                        In short, doing that in Swift causes a runtime
error:

                        leta =[1,2,3]
                        letb =a[0..<5]
                        print(b)

                        > Error running code:
                        > fatal error: Array index out of range

                        The proposed solution is to slice the array
                    returning all elements
                        that are below the half-open operator, even
                    though the number of
                        elements is lesser than the ending of the
                    half-open operator. So the
                        example above would return [1,2,3].
                        We can see this very behaviour in other
                    languages, such as Python and
                        Ruby as shown in the proposal draft.

                        This would eliminate the need for verifications
                    on the array size
                        before slicing it -- and consequently runtime
                    errors in cases when
                        the programmer didn't.

                        Viewing that it is my very first proposal, any
                    feedback will be helpful.

                        Thanks!

                        Luis Henrique Borges
                        @luishborges

                    _______________________________________________
                    swift-evolution mailing list
                    swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto: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 <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

_______________________________________________

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

I brought these up because the current implementation produces an error in these cases. You have to insert additional min/max operations.

···

Am 15.05.2016 um 16:38 schrieb Luis Henrique B. Sousa <lshsousa@gmail.com>:

Exactly, the idea is to return an empty array just like other languages do. (e.g. python)

- Luis

On Sun, May 15, 2016 at 10:13 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

On 15.05.2016 0:09, Maximilian Hünenberger via swift-evolution wrote:
One point which should be discussed is the following behaviour:

let array = [0]
// ranges are completely out of bounds and produce an error
array[clamping: 1...2] // error
array[clamping: -2...-1] // error

Should a range which has no intersection with the indices of the collection
produce an error or just clamp to 0..<0 respectively endIndex..<endIndex?

I expect it will returns i.e. empty array, as no elements with 1...2(-2..-1) indexes in the array. I understand `clamping` similar as 'bounded','in these bounds'. And as soon as [0,1,2,3,4][clamping:2...10] will silently move the right position to allowed index(4), and [0,1,2,3,4][clamping:-2...0] will move left position to 0, I expect that in [0][clamping: 1...2] will try to move both limits to allowed, and as no intersection - silently return empty array.

Best regards
Maximilian

Am 13.05.2016 um 17:10 schrieb Luis Henrique B. Sousa via swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

It seems that there is a consensus that this proposal might be a good
addition to the standard library. All comments on this thread in the past
few weeks were related to naming, not around the behaviour or validity of
the proposed methods. So I will submit this proposal for review very soon
assuming that nobody else has strong arguments against it. :-)

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

If you have any corrections or suggestions to the proposal text itself,
please comment on this gist:
nnnn-more-lenient-collections-subscripts.md · GitHub
(or pull request to my repo)

Regards,

- Luis

On Tue, May 10, 2016 at 4:13 PM, Luis Henrique B. Sousa >>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

    Please let me know if you have more suggestions or corrections on
    this proposal.
    I'm tempted to submit it for review. :-)

    - Luis

    On Tue, May 10, 2016 at 8:53 AM, Luis Henrique B. Sousa >>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

        It sounds good, thanks for you suggestions @Vladimir, @Patrick
        and @Brent.

        I've just updated the proposal:
        https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md#detailed-design

        - Luis

        On Tue, May 10, 2016 at 6:50 AM, Vladimir.S via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

            Yes, I feel like 'within' is much better than 'bounded'.

            How about such changes in proposal:

            a[bounded: -1 ..< 5] --> a[within: -1 ..< 5] (or a[inside:
            -1 ..< 5] )

            a[optional: 0 ..< 5] --> a[checking: 0 ..< 5]
            a[optional: 5] --> a[checking: 5]

            ?

            On 10.05.2016 6:27, Patrick Smith via swift-evolution wrote:

                I like the idea of the of the bounded subscript, however
                the optional one I
                feel could be used for clumsy code.

                .first and .last have value, but once you start stepping
                several arbitrary
                indices in, then that code is likely fragile?

                I can think of ‘within’, ‘inside’ and ‘intersecting’ as
                alternative names
                for ‘bounded’ that attempt to explain what is going on:

                let a = [1, 2, 3]

                a[within: 0 ..< 5] // [1, 2, 3]
                a[inside: 0 ..< 5] // [1, 2, 3]
                a[intersecting: 0 ..< 5] // [1, 2, 3]

                    On 28 Apr 2016, at 10:11 PM, Luis Henrique B. Sousa
                    via swift-evolution
                    <swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto:swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>>> wrote:

                    As we have discussed throughout this thread, the
                    initial proposal was
                    modified to include alternative subscript methods
                    instead of modifying
                    the default operator/subscript behaviour.
                    The first draft is
                    here:
                    https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

                    I've also put this as a gist so that you can leave
                    comments with respect
                    to the proposal document itself. Any suggestion or
                    help is very welcome.
                    nnnn-more-lenient-collections-subscripts.md · GitHub

                    Regards,

                    - Luis

                    On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B. Sousa >>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com> >>>> <mailto:lshsousa@gmail.com >>>> >>>> <mailto:lshsousa@gmail.com>>> wrote:

                        This proposal seeks to provide a safer ..< (aka
                    half-open range
                        operator) in order to avoid **Array index out of
                    range** errors in
                        execution time.

                        Here is my first draft for this proposal:

                    https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md

                        In short, doing that in Swift causes a runtime error:

                        leta =[1,2,3]
                        letb =a[0..<5]
                        print(b)

                        > Error running code:
                        > fatal error: Array index out of range

                        The proposed solution is to slice the array
                    returning all elements
                        that are below the half-open operator, even
                    though the number of
                        elements is lesser than the ending of the
                    half-open operator. So the
                        example above would return [1,2,3].
                        We can see this very behaviour in other
                    languages, such as Python and
                        Ruby as shown in the proposal draft.

                        This would eliminate the need for verifications
                    on the array size
                        before slicing it -- and consequently runtime
                    errors in cases when
                        the programmer didn't.

                        Viewing that it is my very first proposal, any
                    feedback will be helpful.

                        Thanks!

                        Luis Henrique Borges
                        @luishborges

                    _______________________________________________
                    swift-evolution mailing list
                    swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto: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 <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

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

Yes. The suggested implementation does use min/max:

- Luis

···

On Sun, May 15, 2016 at 3:42 PM, Maximilian Hünenberger < m.huenenberger@me.com> wrote:

I brought these up because the current implementation produces an error in
these cases. You have to insert additional min/max operations.

Am 15.05.2016 um 16:38 schrieb Luis Henrique B. Sousa <lshsousa@gmail.com > >:

Exactly, the idea is to return an empty array just like other languages
do. (e.g. python)

- Luis

On Sun, May 15, 2016 at 10:13 AM, Vladimir.S via swift-evolution < > swift-evolution@swift.org> wrote:

On 15.05.2016 0:09, Maximilian Hünenberger via swift-evolution wrote:

One point which should be discussed is the following behaviour:

let array = [0]
// ranges are completely out of bounds and produce an error
array[clamping: 1...2] // error
array[clamping: -2...-1] // error

Should a range which has no intersection with the indices of the
collection
produce an error or just clamp to 0..<0 respectively endIndex..<endIndex?

I expect it will returns i.e. empty array, as no elements with
1...2(-2..-1) indexes in the array. I understand `clamping` similar as
'bounded','in these bounds'. And as soon as [0,1,2,3,4][clamping:2...10]
will silently move the right position to allowed index(4), and
[0,1,2,3,4][clamping:-2...0] will move left position to 0, I expect that
in [0][clamping: 1...2] will try to move both limits to allowed, and as no
intersection - silently return empty array.

Best regards
Maximilian

Am 13.05.2016 um 17:10 schrieb Luis Henrique B. Sousa via swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

It seems that there is a consensus that this proposal might be a good

addition to the standard library. All comments on this thread in the
past
few weeks were related to naming, not around the behaviour or validity
of
the proposed methods. So I will submit this proposal for review very
soon
assuming that nobody else has strong arguments against it. :-)

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

If you have any corrections or suggestions to the proposal text itself,
please comment on this gist:
nnnn-more-lenient-collections-subscripts.md · GitHub
(or pull request to my repo)

Regards,

- Luis

On Tue, May 10, 2016 at 4:13 PM, Luis Henrique B. Sousa >>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

    Please let me know if you have more suggestions or corrections on
    this proposal.
    I'm tempted to submit it for review. :-)

    - Luis

    On Tue, May 10, 2016 at 8:53 AM, Luis Henrique B. Sousa >>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

        It sounds good, thanks for you suggestions @Vladimir, @Patrick
        and @Brent.

        I've just updated the proposal:

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

        - Luis

        On Tue, May 10, 2016 at 6:50 AM, Vladimir.S via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> >>>> wrote:

            Yes, I feel like 'within' is much better than 'bounded'.

            How about such changes in proposal:

            a[bounded: -1 ..< 5] --> a[within: -1 ..< 5] (or
a[inside:
            -1 ..< 5] )

            a[optional: 0 ..< 5] --> a[checking: 0 ..< 5]
            a[optional: 5] --> a[checking: 5]

            ?

            On 10.05.2016 6:27, Patrick Smith via swift-evolution wrote:

                I like the idea of the of the bounded subscript, however
                the optional one I
                feel could be used for clumsy code.

                .first and .last have value, but once you start stepping
                several arbitrary
                indices in, then that code is likely fragile?

                I can think of ‘within’, ‘inside’ and ‘intersecting’ as
                alternative names
                for ‘bounded’ that attempt to explain what is going on:

                let a = [1, 2, 3]

                a[within: 0 ..< 5] // [1, 2, 3]
                a[inside: 0 ..< 5] // [1, 2, 3]
                a[intersecting: 0 ..< 5] // [1, 2, 3]

                    On 28 Apr 2016, at 10:11 PM, Luis Henrique B. Sousa
                    via swift-evolution
                    <swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto:swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>>> wrote:

                    As we have discussed throughout this thread, the
                    initial proposal was
                    modified to include alternative subscript methods
                    instead of modifying
                    the default operator/subscript behaviour.
                    The first draft is
                    here:

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

                    I've also put this as a gist so that you can leave
                    comments with respect
                    to the proposal document itself. Any suggestion or
                    help is very welcome.

nnnn-more-lenient-collections-subscripts.md · GitHub

                    Regards,

                    - Luis

                    On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B.
Sousa
                    <lshsousa@gmail.com <mailto:lshsousa@gmail.com>
                    <mailto:lshsousa@gmail.com

                    <mailto:lshsousa@gmail.com>>> wrote:

                        This proposal seeks to provide a safer ..< (aka
                    half-open range
                        operator) in order to avoid **Array index out of
                    range** errors in
                        execution time.

                        Here is my first draft for this proposal:

https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md

                        In short, doing that in Swift causes a runtime
error:

                        leta =[1,2,3]
                        letb =a[0..<5]
                        print(b)

                        > Error running code:
                        > fatal error: Array index out of range

                        The proposed solution is to slice the array
                    returning all elements
                        that are below the half-open operator, even
                    though the number of
                        elements is lesser than the ending of the
                    half-open operator. So the
                        example above would return [1,2,3].
                        We can see this very behaviour in other
                    languages, such as Python and
                        Ruby as shown in the proposal draft.

                        This would eliminate the need for verifications
                    on the array size
                        before slicing it -- and consequently runtime
                    errors in cases when
                        the programmer didn't.

                        Viewing that it is my very first proposal, any
                    feedback will be helpful.

                        Thanks!

                        Luis Henrique Borges
                        @luishborges

                    _______________________________________________
                    swift-evolution mailing list
                    swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto: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 <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

_______________________________________________

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

While it is true that it uses min and max, you have to add additional min max in order to achieve the desired behavior.

So the implementation should be: (also considering (hopefully all) recent naming/index model updates)

// Index is already Comparable
extension Collection {

    subscript(clamping range: Range<Index>) -> SubSequence {
        // ---> here you have to use the additional min/max
        let start = min(max(startIndex, range.startIndex), endIndex)
        let end = max(min(endIndex, range.endIndex), startIndex)
        return self[start ..< end]

        // ---> or as alternative, probably a bit less performant but Swiftier
        return self[range.clamping(startIndex..<endIndex)]
    }

    subscript(checking range: Range<Index>) -> SubSequence? {
        guard range.startIndex >= startIndex && range.endIndex <= endIndex
            else { return nil }
        return self[range]
    }

    subscript(checking index: Index) -> Generator.Element? {
        // ---> minor syntax update *
        guard self.indices.contains(index)
            else { return nil }
        return self[index]
    }

}

* I'm not sure it is worth the performance cost for arbitrary indices collection with O(n) search. I could imagine Set and Dictionary indices cannot be easily validated in comparison to Array indices. However this approach is more general and handles non trivial index collections where there is no guarantee that any index between startIndex and endIndex is a valid one.
The same arguments also apply to `subscript(checking range ...)` where you could validate start and endIndex of the range.

Best regards
Maximilian

···

Am 16.05.2016 um 09:45 schrieb Luis Henrique B. Sousa <lshsousa@gmail.com>:

Yes. The suggested implementation does use min/max:

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

- Luis

On Sun, May 15, 2016 at 3:42 PM, Maximilian Hünenberger <m.huenenberger@me.com> wrote:
I brought these up because the current implementation produces an error in these cases. You have to insert additional min/max operations.

Am 15.05.2016 um 16:38 schrieb Luis Henrique B. Sousa <lshsousa@gmail.com>:

Exactly, the idea is to return an empty array just like other languages do. (e.g. python)

- Luis

On Sun, May 15, 2016 at 10:13 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

On 15.05.2016 0:09, Maximilian Hünenberger via swift-evolution wrote:
One point which should be discussed is the following behaviour:

let array = [0]
// ranges are completely out of bounds and produce an error
array[clamping: 1...2] // error
array[clamping: -2...-1] // error

Should a range which has no intersection with the indices of the collection
produce an error or just clamp to 0..<0 respectively endIndex..<endIndex?

I expect it will returns i.e. empty array, as no elements with 1...2(-2..-1) indexes in the array. I understand `clamping` similar as 'bounded','in these bounds'. And as soon as [0,1,2,3,4][clamping:2...10] will silently move the right position to allowed index(4), and [0,1,2,3,4][clamping:-2...0] will move left position to 0, I expect that in [0][clamping: 1...2] will try to move both limits to allowed, and as no intersection - silently return empty array.

Best regards
Maximilian

Am 13.05.2016 um 17:10 schrieb Luis Henrique B. Sousa via swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

It seems that there is a consensus that this proposal might be a good
addition to the standard library. All comments on this thread in the past
few weeks were related to naming, not around the behaviour or validity of
the proposed methods. So I will submit this proposal for review very soon
assuming that nobody else has strong arguments against it. :-)

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

If you have any corrections or suggestions to the proposal text itself,
please comment on this gist:
nnnn-more-lenient-collections-subscripts.md · GitHub
(or pull request to my repo)

Regards,

- Luis

On Tue, May 10, 2016 at 4:13 PM, Luis Henrique B. Sousa >>>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

    Please let me know if you have more suggestions or corrections on
    this proposal.
    I'm tempted to submit it for review. :-)

    - Luis

    On Tue, May 10, 2016 at 8:53 AM, Luis Henrique B. Sousa >>>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

        It sounds good, thanks for you suggestions @Vladimir, @Patrick
        and @Brent.

        I've just updated the proposal:
        https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md#detailed-design

        - Luis

        On Tue, May 10, 2016 at 6:50 AM, Vladimir.S via swift-evolution >>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

            Yes, I feel like 'within' is much better than 'bounded'.

            How about such changes in proposal:

            a[bounded: -1 ..< 5] --> a[within: -1 ..< 5] (or a[inside:
            -1 ..< 5] )

            a[optional: 0 ..< 5] --> a[checking: 0 ..< 5]
            a[optional: 5] --> a[checking: 5]

            ?

            On 10.05.2016 6:27, Patrick Smith via swift-evolution wrote:

                I like the idea of the of the bounded subscript, however
                the optional one I
                feel could be used for clumsy code.

                .first and .last have value, but once you start stepping
                several arbitrary
                indices in, then that code is likely fragile?

                I can think of ‘within’, ‘inside’ and ‘intersecting’ as
                alternative names
                for ‘bounded’ that attempt to explain what is going on:

                let a = [1, 2, 3]

                a[within: 0 ..< 5] // [1, 2, 3]
                a[inside: 0 ..< 5] // [1, 2, 3]
                a[intersecting: 0 ..< 5] // [1, 2, 3]

                    On 28 Apr 2016, at 10:11 PM, Luis Henrique B. Sousa
                    via swift-evolution
                    <swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto:swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>>> wrote:

                    As we have discussed throughout this thread, the
                    initial proposal was
                    modified to include alternative subscript methods
                    instead of modifying
                    the default operator/subscript behaviour.
                    The first draft is
                    here:
                    https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

                    I've also put this as a gist so that you can leave
                    comments with respect
                    to the proposal document itself. Any suggestion or
                    help is very welcome.
                    nnnn-more-lenient-collections-subscripts.md · GitHub

                    Regards,

                    - Luis

                    On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B. Sousa >>>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com> >>>>>> <mailto:lshsousa@gmail.com >>>>>> >>>>>> <mailto:lshsousa@gmail.com>>> wrote:

                        This proposal seeks to provide a safer ..< (aka
                    half-open range
                        operator) in order to avoid **Array index out of
                    range** errors in
                        execution time.

                        Here is my first draft for this proposal:

                    https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md

                        In short, doing that in Swift causes a runtime error:

                        leta =[1,2,3]
                        letb =a[0..<5]
                        print(b)

                        > Error running code:
                        > fatal error: Array index out of range

                        The proposed solution is to slice the array
                    returning all elements
                        that are below the half-open operator, even
                    though the number of
                        elements is lesser than the ending of the
                    half-open operator. So the
                        example above would return [1,2,3].
                        We can see this very behaviour in other
                    languages, such as Python and
                        Ruby as shown in the proposal draft.

                        This would eliminate the need for verifications
                    on the array size
                        before slicing it -- and consequently runtime
                    errors in cases when
                        the programmer didn't.

                        Viewing that it is my very first proposal, any
                    feedback will be helpful.

                        Thanks!

                        Luis Henrique Borges
                        @luishborges

                    _______________________________________________
                    swift-evolution mailing list
                    swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto: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 <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

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

Many thanks, @Maximilian. I'm also not sure about the performance cost, but I think it is worth it.
So I just updated the proposal also including the additional min/max you have suggested (thanks once again):
Proposal: more lenient subscript methods over Collections by luish · Pull Request #328 · apple/swift-evolution · GitHub

Best regards,

- Luis

The new Range types have a clamped(to:) method that should do what you need.

···

On May 17, 2016, at 5:18 PM, Luis Henrique B. Sousa via swift-evolution <swift-evolution@swift.org> wrote:

On Tue, May 17, 2016 at 10:32 PM, Maximilian Hünenberger <m.huenenberger@me.com> wrote:
While it is true that it uses min and max, you have to add additional min max in order to achieve the desired behavior.

So the implementation should be: (also considering (hopefully all) recent naming/index model updates)

// Index is already Comparable
extension Collection {

    subscript(clamping range: Range<Index>) -> SubSequence {
        // ---> here you have to use the additional min/max
        let start = min(max(startIndex, range.startIndex), endIndex)
        let end = max(min(endIndex, range.endIndex), startIndex)
        return self[start ..< end]

        // ---> or as alternative, probably a bit less performant but Swiftier
        return self[range.clamping(startIndex..<endIndex)]
    }

    subscript(checking range: Range<Index>) -> SubSequence? {
        guard range.startIndex >= startIndex && range.endIndex <= endIndex
            else { return nil }
        return self[range]
    }

    subscript(checking index: Index) -> Generator.Element? {
        // ---> minor syntax update *
        guard self.indices.contains(index)
            else { return nil }
        return self[index]
    }

}

* I'm not sure it is worth the performance cost for arbitrary indices collection with O(n) search. I could imagine Set and Dictionary indices cannot be easily validated in comparison to Array indices. However this approach is more general and handles non trivial index collections where there is no guarantee that any index between startIndex and endIndex is a valid one.
The same arguments also apply to `subscript(checking range ...)` where you could validate start and endIndex of the range.

Best regards
Maximilian

Am 16.05.2016 um 09:45 schrieb Luis Henrique B. Sousa <lshsousa@gmail.com>:

Yes. The suggested implementation does use min/max:

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

- Luis

On Sun, May 15, 2016 at 3:42 PM, Maximilian Hünenberger <m.huenenberger@me.com> wrote:
I brought these up because the current implementation produces an error in these cases. You have to insert additional min/max operations.

Am 15.05.2016 um 16:38 schrieb Luis Henrique B. Sousa <lshsousa@gmail.com>:

Exactly, the idea is to return an empty array just like other languages do. (e.g. python)

- Luis

On Sun, May 15, 2016 at 10:13 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

On 15.05.2016 0:09, Maximilian Hünenberger via swift-evolution wrote:
One point which should be discussed is the following behaviour:

let array = [0]
// ranges are completely out of bounds and produce an error
array[clamping: 1...2] // error
array[clamping: -2...-1] // error

Should a range which has no intersection with the indices of the collection
produce an error or just clamp to 0..<0 respectively endIndex..<endIndex?

I expect it will returns i.e. empty array, as no elements with 1...2(-2..-1) indexes in the array. I understand `clamping` similar as 'bounded','in these bounds'. And as soon as [0,1,2,3,4][clamping:2...10] will silently move the right position to allowed index(4), and [0,1,2,3,4][clamping:-2...0] will move left position to 0, I expect that in [0][clamping: 1...2] will try to move both limits to allowed, and as no intersection - silently return empty array.

Best regards
Maximilian

Am 13.05.2016 um 17:10 schrieb Luis Henrique B. Sousa via swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

It seems that there is a consensus that this proposal might be a good
addition to the standard library. All comments on this thread in the past
few weeks were related to naming, not around the behaviour or validity of
the proposed methods. So I will submit this proposal for review very soon
assuming that nobody else has strong arguments against it. :-)

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

If you have any corrections or suggestions to the proposal text itself,
please comment on this gist:
nnnn-more-lenient-collections-subscripts.md · GitHub
(or pull request to my repo)

Regards,

- Luis

On Tue, May 10, 2016 at 4:13 PM, Luis Henrique B. Sousa >>>>>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

    Please let me know if you have more suggestions or corrections on
    this proposal.
    I'm tempted to submit it for review. :-)

    - Luis

    On Tue, May 10, 2016 at 8:53 AM, Luis Henrique B. Sousa >>>>>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

        It sounds good, thanks for you suggestions @Vladimir, @Patrick
        and @Brent.

        I've just updated the proposal:
        https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md#detailed-design

        - Luis

        On Tue, May 10, 2016 at 6:50 AM, Vladimir.S via swift-evolution >>>>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

            Yes, I feel like 'within' is much better than 'bounded'.

            How about such changes in proposal:

            a[bounded: -1 ..< 5] --> a[within: -1 ..< 5] (or a[inside:
            -1 ..< 5] )

            a[optional: 0 ..< 5] --> a[checking: 0 ..< 5]
            a[optional: 5] --> a[checking: 5]

            ?

            On 10.05.2016 6:27, Patrick Smith via swift-evolution wrote:

                I like the idea of the of the bounded subscript, however
                the optional one I
                feel could be used for clumsy code.

                .first and .last have value, but once you start stepping
                several arbitrary
                indices in, then that code is likely fragile?

                I can think of ‘within’, ‘inside’ and ‘intersecting’ as
                alternative names
                for ‘bounded’ that attempt to explain what is going on:

                let a = [1, 2, 3]

                a[within: 0 ..< 5] // [1, 2, 3]
                a[inside: 0 ..< 5] // [1, 2, 3]
                a[intersecting: 0 ..< 5] // [1, 2, 3]

                    On 28 Apr 2016, at 10:11 PM, Luis Henrique B. Sousa
                    via swift-evolution
                    <swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto:swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>>> wrote:

                    As we have discussed throughout this thread, the
                    initial proposal was
                    modified to include alternative subscript methods
                    instead of modifying
                    the default operator/subscript behaviour.
                    The first draft is
                    here:
                    https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

                    I've also put this as a gist so that you can leave
                    comments with respect
                    to the proposal document itself. Any suggestion or
                    help is very welcome.
                    nnnn-more-lenient-collections-subscripts.md · GitHub

                    Regards,

                    - Luis

                    On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B. Sousa >>>>>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com> >>>>>>>> <mailto:lshsousa@gmail.com >>>>>>>> >>>>>>>> <mailto:lshsousa@gmail.com>>> wrote:

                        This proposal seeks to provide a safer ..< (aka
                    half-open range
                        operator) in order to avoid **Array index out of
                    range** errors in
                        execution time.

                        Here is my first draft for this proposal:

                    https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md

                        In short, doing that in Swift causes a runtime error:

                        leta =[1,2,3]
                        letb =a[0..<5]
                        print(b)

                        > Error running code:
                        > fatal error: Array index out of range

                        The proposed solution is to slice the array
                    returning all elements
                        that are below the half-open operator, even
                    though the number of
                        elements is lesser than the ending of the
                    half-open operator. So the
                        example above would return [1,2,3].
                        We can see this very behaviour in other
                    languages, such as Python and
                        Ruby as shown in the proposal draft.

                        This would eliminate the need for verifications
                    on the array size
                        before slicing it -- and consequently runtime
                    errors in cases when
                        the programmer didn't.

                        Viewing that it is my very first proposal, any
                    feedback will be helpful.

                        Thanks!

                        Luis Henrique Borges
                        @luishborges

                    _______________________________________________
                    swift-evolution mailing list
                    swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto: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 <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

_______________________________________________
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

Many thanks, @Maximilian. I'm also not sure about the performance cost, but
I think it is worth it.
So I just updated the proposal also including the additional min/max you
have suggested (thanks once again):

Best regards,

- Luis

···

On Tue, May 17, 2016 at 10:32 PM, Maximilian Hünenberger < m.huenenberger@me.com> wrote:

While it is true that it uses min and max, you have to add *additional
min max* in order to achieve the desired behavior.

So the implementation should be: (also considering (hopefully all) recent
naming/index model updates)

// Index is already Comparable
extension Collection {

    subscript(clamping range: Range<Index>) -> SubSequence {
        // ---> here you have to use the additional min/max
        let start = min(max(startIndex, range.startIndex), endIndex)
        let end = max(min(endIndex, range.endIndex), startIndex)
        return self[start ..< end]

        // ---> or as alternative, probably a bit less performant but
Swiftier
        return self[range.clamping(startIndex..<endIndex)]
    }

    subscript(checking range: Range<Index>) -> SubSequence? {
        guard range.startIndex >= startIndex && range.endIndex <= endIndex
            else { return nil }
        return self[range]
    }

    subscript(checking index: Index) -> Generator.Element? {
        // ---> minor syntax update *
        guard self.indices.contains(index)
            else { return nil }
        return self[index]
    }

}

* I'm not sure it is worth the performance cost for arbitrary indices
collection with O(n) search. I could imagine Set and Dictionary indices
cannot be easily validated in comparison to Array indices. However this
approach is more general and handles non trivial index collections where
there is no guarantee that any index between startIndex and endIndex is a
valid one.
The same arguments also apply to `subscript(checking range ...)` where you
could validate start and endIndex of the range.

Best regards
Maximilian

Am 16.05.2016 um 09:45 schrieb Luis Henrique B. Sousa <lshsousa@gmail.com > >:

Yes. The suggested implementation does use min/max:

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

- Luis

On Sun, May 15, 2016 at 3:42 PM, Maximilian Hünenberger < > m.huenenberger@me.com> wrote:

I brought these up because the current implementation produces an error
in these cases. You have to insert additional min/max operations.

Am 15.05.2016 um 16:38 schrieb Luis Henrique B. Sousa <lshsousa@gmail.com >> >:

Exactly, the idea is to return an empty array just like other languages
do. (e.g. python)

- Luis

On Sun, May 15, 2016 at 10:13 AM, Vladimir.S via swift-evolution < >> swift-evolution@swift.org> wrote:

On 15.05.2016 0:09, Maximilian Hünenberger via swift-evolution wrote:

One point which should be discussed is the following behaviour:

let array = [0]
// ranges are completely out of bounds and produce an error
array[clamping: 1...2] // error
array[clamping: -2...-1] // error

Should a range which has no intersection with the indices of the
collection
produce an error or just clamp to 0..<0 respectively
endIndex..<endIndex?

I expect it will returns i.e. empty array, as no elements with
1...2(-2..-1) indexes in the array. I understand `clamping` similar as
'bounded','in these bounds'. And as soon as [0,1,2,3,4][clamping:2...10]
will silently move the right position to allowed index(4), and
[0,1,2,3,4][clamping:-2...0] will move left position to 0, I expect that
in [0][clamping: 1...2] will try to move both limits to allowed, and as no
intersection - silently return empty array.

Best regards
Maximilian

Am 13.05.2016 um 17:10 schrieb Luis Henrique B. Sousa via >>>> swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

It seems that there is a consensus that this proposal might be a good

addition to the standard library. All comments on this thread in the
past
few weeks were related to naming, not around the behaviour or validity
of
the proposed methods. So I will submit this proposal for review very
soon
assuming that nobody else has strong arguments against it. :-)

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

If you have any corrections or suggestions to the proposal text itself,
please comment on this gist:
nnnn-more-lenient-collections-subscripts.md · GitHub
(or pull request to my repo)

Regards,

- Luis

On Tue, May 10, 2016 at 4:13 PM, Luis Henrique B. Sousa >>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

    Please let me know if you have more suggestions or corrections on
    this proposal.
    I'm tempted to submit it for review. :-)

    - Luis

    On Tue, May 10, 2016 at 8:53 AM, Luis Henrique B. Sousa >>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

        It sounds good, thanks for you suggestions @Vladimir, @Patrick
        and @Brent.

        I've just updated the proposal:

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

        - Luis

        On Tue, May 10, 2016 at 6:50 AM, Vladimir.S via swift-evolution >>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> >>>>> wrote:

            Yes, I feel like 'within' is much better than 'bounded'.

            How about such changes in proposal:

            a[bounded: -1 ..< 5] --> a[within: -1 ..< 5] (or
a[inside:
            -1 ..< 5] )

            a[optional: 0 ..< 5] --> a[checking: 0 ..< 5]
            a[optional: 5] --> a[checking: 5]

            ?

            On 10.05.2016 6:27, Patrick Smith via swift-evolution >>>>> wrote:

                I like the idea of the of the bounded subscript,
however
                the optional one I
                feel could be used for clumsy code.

                .first and .last have value, but once you start
stepping
                several arbitrary
                indices in, then that code is likely fragile?

                I can think of ‘within’, ‘inside’ and ‘intersecting’ as
                alternative names
                for ‘bounded’ that attempt to explain what is going on:

                let a = [1, 2, 3]

                a[within: 0 ..< 5] // [1, 2, 3]
                a[inside: 0 ..< 5] // [1, 2, 3]
                a[intersecting: 0 ..< 5] // [1, 2, 3]

                    On 28 Apr 2016, at 10:11 PM, Luis Henrique B. Sousa
                    via swift-evolution
                    <swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto:swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>>> wrote:

                    As we have discussed throughout this thread, the
                    initial proposal was
                    modified to include alternative subscript methods
                    instead of modifying
                    the default operator/subscript behaviour.
                    The first draft is
                    here:

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

                    I've also put this as a gist so that you can leave
                    comments with respect
                    to the proposal document itself. Any suggestion or
                    help is very welcome.

nnnn-more-lenient-collections-subscripts.md · GitHub

                    Regards,

                    - Luis

                    On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B.
Sousa
                    <lshsousa@gmail.com <mailto:lshsousa@gmail.com>
                    <mailto:lshsousa@gmail.com

                    <mailto:lshsousa@gmail.com>>> wrote:

                        This proposal seeks to provide a safer ..< (aka
                    half-open range
                        operator) in order to avoid **Array index out
of
                    range** errors in
                        execution time.

                        Here is my first draft for this proposal:

https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md

                        In short, doing that in Swift causes a runtime
error:

                        leta =[1,2,3]
                        letb =a[0..<5]
                        print(b)

                        > Error running code:
                        > fatal error: Array index out of range

                        The proposed solution is to slice the array
                    returning all elements
                        that are below the half-open operator, even
                    though the number of
                        elements is lesser than the ending of the
                    half-open operator. So the
                        example above would return [1,2,3].
                        We can see this very behaviour in other
                    languages, such as Python and
                        Ruby as shown in the proposal draft.

                        This would eliminate the need for verifications
                    on the array size
                        before slicing it -- and consequently runtime
                    errors in cases when
                        the programmer didn't.

                        Viewing that it is my very first proposal, any
                    feedback will be helpful.

                        Thanks!

                        Luis Henrique Borges
                        @luishborges

                    _______________________________________________
                    swift-evolution mailing list
                    swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto: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 <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

_______________________________________________

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

Yes @Nate, thanks for pointing that out. It was mentioned here:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160411/014807.html

You mean it should do what we need in order to avoid those min/max
operations, right? Just asking because the discussion before (in the link
above) was regards to the validity of this proposal considering that we
could have exactly the same behaviour if using `Range.clamped(to:)` before
applying the `subscript(range:)`. But I think our arguments on having a
more clear and handy way to do that are valid so far.

- Luis

···

On Tue, May 17, 2016 at 11:54 PM, Nate Cook <nate@natecook.com> wrote:

On May 17, 2016, at 5:18 PM, Luis Henrique B. Sousa via swift-evolution < > swift-evolution@swift.org> wrote:

Many thanks, @Maximilian. I'm also not sure about the performance cost,
but I think it is worth it.
So I just updated the proposal also including the additional min/max you
have suggested (thanks once again):
Proposal: more lenient subscript methods over Collections by luish · Pull Request #328 · apple/swift-evolution · GitHub

Best regards,

- Luis

The new Range types have a clamped(to:) method that should do what you
need.

Range — SwiftDoc.org

On Tue, May 17, 2016 at 10:32 PM, Maximilian Hünenberger < > m.huenenberger@me.com> wrote:

While it is true that it uses min and max, you have to add *additional
min max* in order to achieve the desired behavior.

So the implementation should be: (also considering (hopefully all) recent
naming/index model updates)

// Index is already Comparable
extension Collection {

    subscript(clamping range: Range<Index>) -> SubSequence {
        // ---> here you have to use the additional min/max
        let start = min(max(startIndex, range.startIndex), endIndex)
        let end = max(min(endIndex, range.endIndex), startIndex)
        return self[start ..< end]

        // ---> or as alternative, probably a bit less performant but
Swiftier
        return self[range.clamping(startIndex..<endIndex)]
    }

    subscript(checking range: Range<Index>) -> SubSequence? {
        guard range.startIndex >= startIndex && range.endIndex <= endIndex
            else { return nil }
        return self[range]
    }

    subscript(checking index: Index) -> Generator.Element? {
        // ---> minor syntax update *
        guard self.indices.contains(index)
            else { return nil }
        return self[index]
    }

}

* I'm not sure it is worth the performance cost for arbitrary indices
collection with O(n) search. I could imagine Set and Dictionary indices
cannot be easily validated in comparison to Array indices. However this
approach is more general and handles non trivial index collections where
there is no guarantee that any index between startIndex and endIndex is a
valid one.
The same arguments also apply to `subscript(checking range ...)` where
you could validate start and endIndex of the range.

Best regards
Maximilian

Am 16.05.2016 um 09:45 schrieb Luis Henrique B. Sousa <lshsousa@gmail.com >> >:

Yes. The suggested implementation does use min/max:

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

- Luis

On Sun, May 15, 2016 at 3:42 PM, Maximilian Hünenberger < >> m.huenenberger@me.com> wrote:

I brought these up because the current implementation produces an error
in these cases. You have to insert additional min/max operations.

Am 15.05.2016 um 16:38 schrieb Luis Henrique B. Sousa < >>> lshsousa@gmail.com>:

Exactly, the idea is to return an empty array just like other languages
do. (e.g. python)

- Luis

On Sun, May 15, 2016 at 10:13 AM, Vladimir.S via swift-evolution < >>> swift-evolution@swift.org> wrote:

On 15.05.2016 0:09, Maximilian Hünenberger via swift-evolution wrote:

One point which should be discussed is the following behaviour:

let array = [0]
// ranges are completely out of bounds and produce an error
array[clamping: 1...2] // error
array[clamping: -2...-1] // error

Should a range which has no intersection with the indices of the
collection
produce an error or just clamp to 0..<0 respectively
endIndex..<endIndex?

I expect it will returns i.e. empty array, as no elements with
1...2(-2..-1) indexes in the array. I understand `clamping` similar as
'bounded','in these bounds'. And as soon as [0,1,2,3,4][clamping:2...10]
will silently move the right position to allowed index(4), and
[0,1,2,3,4][clamping:-2...0] will move left position to 0, I expect that
in [0][clamping: 1...2] will try to move both limits to allowed, and as no
intersection - silently return empty array.

Best regards
Maximilian

Am 13.05.2016 um 17:10 schrieb Luis Henrique B. Sousa via >>>>> swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

It seems that there is a consensus that this proposal might be a good

addition to the standard library. All comments on this thread in the
past
few weeks were related to naming, not around the behaviour or
validity of
the proposed methods. So I will submit this proposal for review very
soon
assuming that nobody else has strong arguments against it. :-)

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

If you have any corrections or suggestions to the proposal text
itself,
please comment on this gist:
nnnn-more-lenient-collections-subscripts.md · GitHub
(or pull request to my repo)

Regards,

- Luis

On Tue, May 10, 2016 at 4:13 PM, Luis Henrique B. Sousa >>>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

    Please let me know if you have more suggestions or corrections on
    this proposal.
    I'm tempted to submit it for review. :-)

    - Luis

    On Tue, May 10, 2016 at 8:53 AM, Luis Henrique B. Sousa >>>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

        It sounds good, thanks for you suggestions @Vladimir, @Patrick
        and @Brent.

        I've just updated the proposal:

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

        - Luis

        On Tue, May 10, 2016 at 6:50 AM, Vladimir.S via >>>>>> swift-evolution >>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> >>>>>> wrote:

            Yes, I feel like 'within' is much better than 'bounded'.

            How about such changes in proposal:

            a[bounded: -1 ..< 5] --> a[within: -1 ..< 5] (or
a[inside:
            -1 ..< 5] )

            a[optional: 0 ..< 5] --> a[checking: 0 ..< 5]
            a[optional: 5] --> a[checking: 5]

            ?

            On 10.05.2016 6:27, Patrick Smith via swift-evolution >>>>>> wrote:

                I like the idea of the of the bounded subscript,
however
                the optional one I
                feel could be used for clumsy code.

                .first and .last have value, but once you start
stepping
                several arbitrary
                indices in, then that code is likely fragile?

                I can think of ‘within’, ‘inside’ and ‘intersecting’
as
                alternative names
                for ‘bounded’ that attempt to explain what is going
on:

                let a = [1, 2, 3]

                a[within: 0 ..< 5] // [1, 2, 3]
                a[inside: 0 ..< 5] // [1, 2, 3]
                a[intersecting: 0 ..< 5] // [1, 2, 3]

                    On 28 Apr 2016, at 10:11 PM, Luis Henrique B.
Sousa
                    via swift-evolution
                    <swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto:swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>>> wrote:

                    As we have discussed throughout this thread, the
                    initial proposal was
                    modified to include alternative subscript methods
                    instead of modifying
                    the default operator/subscript behaviour.
                    The first draft is
                    here:

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

                    I've also put this as a gist so that you can leave
                    comments with respect
                    to the proposal document itself. Any suggestion or
                    help is very welcome.

nnnn-more-lenient-collections-subscripts.md · GitHub

                    Regards,

                    - Luis

                    On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B.
Sousa
                    <lshsousa@gmail.com <mailto:lshsousa@gmail.com>
                    <mailto:lshsousa@gmail.com

                    <mailto:lshsousa@gmail.com>>> wrote:

                        This proposal seeks to provide a safer ..<
(aka
                    half-open range
                        operator) in order to avoid **Array index out
of
                    range** errors in
                        execution time.

                        Here is my first draft for this proposal:

https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md

                        In short, doing that in Swift causes a
runtime error:

                        leta =[1,2,3]
                        letb =a[0..<5]
                        print(b)

                        > Error running code:
                        > fatal error: Array index out of range

                        The proposed solution is to slice the array
                    returning all elements
                        that are below the half-open operator, even
                    though the number of
                        elements is lesser than the ending of the
                    half-open operator. So the
                        example above would return [1,2,3].
                        We can see this very behaviour in other
                    languages, such as Python and
                        Ruby as shown in the proposal draft.

                        This would eliminate the need for
verifications
                    on the array size
                        before slicing it -- and consequently runtime
                    errors in cases when
                        the programmer didn't.

                        Viewing that it is my very first proposal, any
                    feedback will be helpful.

                        Thanks!

                        Luis Henrique Borges
                        @luishborges

                    _______________________________________________
                    swift-evolution mailing list
                    swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto: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 <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

_______________________________________________

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

As regards some comments in the pull request
<https://github.com/apple/swift-evolution/pull/328&gt; (thanks @Adriano
Ferreira), I have updated the implementation
<https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md#detailed-design&gt;
to
Swift 3.0. It now uses `clamped(to:)` as suggested by @Nate -- I think it
does look much more elegant. :-)

You can see the current code, run and test it from here:
https://swiftlang.ng.bluemix.net/#/repl/578ccabaf0ebe4d91be1e605

Considering that there were some other threads and drafts around this very
subject, more feedback and discussion are required on this idea. Even with
the new Range.clamped(to:) method, I still think that this addition could
be handy and useful. I do know that it is a very simple extension and that
it doesn't do much behind the scenes, but I would like to have it available
and ready to use when convenient.

Furthermore, it's not all about the "syntax sugar" aspect, it's something
to discuss when the fail-fast perspective doesn't apply directly, when the
operation doesn't necessarily causes a bug if it fails, when we'd rather
have the subscript method executing "safely" (controversial term, but you
got my point) than the application crashing in runtime.

There are many cases where I have to add extra code with operations and
validations in order to get subarrays or an element in a specific position.
For example, given an application with some sort of "top 5", currently I
must be careful and check the array size beforehand. I would rather avoid
that and take advantage of a more intuitive and clear solution e.g.
`records[clamping:
0..<5]`, instead of validating that the array is not empty and then
returning something like `records.count > 5 ? records[0..<5] :
records[0..records.count]`.

tl;dr;

After all, I'm just seeking a behaviour that could be compared to what we
have for dictionaries when trying to get the value for a non-existing key:

let dict = ["a": 1, "b": 2]
*> dict["c"] // nil*

let array = [1,2,3]
*> array[5] // fatal error: index out of range*
*> array[0..<5] // fatal error: index out of range*

with this proposal:
*> array[checking: 5] // nil*
*> array[checking: 0..<5] // nil (Optional)*
*> array[clamping: 0..<5] // [1,2,3] (clamped to bounds)*

Regards,
Luis

···

On Tue, May 17, 2016 at 11:54 PM, Nate Cook <nate@natecook.com> wrote:

On May 17, 2016, at 5:18 PM, Luis Henrique B. Sousa via swift-evolution < > swift-evolution@swift.org> wrote:

Many thanks, @Maximilian. I'm also not sure about the performance cost,
but I think it is worth it.
So I just updated the proposal also including the additional min/max you
have suggested (thanks once again):
Proposal: more lenient subscript methods over Collections by luish · Pull Request #328 · apple/swift-evolution · GitHub

Best regards,

- Luis

The new Range types have a clamped(to:) method that should do what you
need.

Range — SwiftDoc.org

On Tue, May 17, 2016 at 10:32 PM, Maximilian Hünenberger < > m.huenenberger@me.com> wrote:

While it is true that it uses min and max, you have to add *additional
min max* in order to achieve the desired behavior.

So the implementation should be: (also considering (hopefully all) recent
naming/index model updates)

// Index is already Comparable
extension Collection {

    subscript(clamping range: Range<Index>) -> SubSequence {
        // ---> here you have to use the additional min/max
        let start = min(max(startIndex, range.startIndex), endIndex)
        let end = max(min(endIndex, range.endIndex), startIndex)
        return self[start ..< end]

        // ---> or as alternative, probably a bit less performant but
Swiftier
        return self[range.clamping(startIndex..<endIndex)]
    }

    subscript(checking range: Range<Index>) -> SubSequence? {
        guard range.startIndex >= startIndex && range.endIndex <= endIndex
            else { return nil }
        return self[range]
    }

    subscript(checking index: Index) -> Generator.Element? {
        // ---> minor syntax update *
        guard self.indices.contains(index)
            else { return nil }
        return self[index]
    }

}

* I'm not sure it is worth the performance cost for arbitrary indices
collection with O(n) search. I could imagine Set and Dictionary indices
cannot be easily validated in comparison to Array indices. However this
approach is more general and handles non trivial index collections where
there is no guarantee that any index between startIndex and endIndex is a
valid one.
The same arguments also apply to `subscript(checking range ...)` where
you could validate start and endIndex of the range.

Best regards
Maximilian

Am 16.05.2016 um 09:45 schrieb Luis Henrique B. Sousa <lshsousa@gmail.com >> >:

Yes. The suggested implementation does use min/max:

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

- Luis

On Sun, May 15, 2016 at 3:42 PM, Maximilian Hünenberger < >> m.huenenberger@me.com> wrote:

I brought these up because the current implementation produces an error
in these cases. You have to insert additional min/max operations.

Am 15.05.2016 um 16:38 schrieb Luis Henrique B. Sousa < >>> lshsousa@gmail.com>:

Exactly, the idea is to return an empty array just like other languages
do. (e.g. python)

- Luis

On Sun, May 15, 2016 at 10:13 AM, Vladimir.S via swift-evolution < >>> swift-evolution@swift.org> wrote:

On 15.05.2016 0:09, Maximilian Hünenberger via swift-evolution wrote:

One point which should be discussed is the following behaviour:

let array = [0]
// ranges are completely out of bounds and produce an error
array[clamping: 1...2] // error
array[clamping: -2...-1] // error

Should a range which has no intersection with the indices of the
collection
produce an error or just clamp to 0..<0 respectively
endIndex..<endIndex?

I expect it will returns i.e. empty array, as no elements with
1...2(-2..-1) indexes in the array. I understand `clamping` similar as
'bounded','in these bounds'. And as soon as [0,1,2,3,4][clamping:2...10]
will silently move the right position to allowed index(4), and
[0,1,2,3,4][clamping:-2...0] will move left position to 0, I expect that
in [0][clamping: 1...2] will try to move both limits to allowed, and as no
intersection - silently return empty array.

Best regards
Maximilian

Am 13.05.2016 um 17:10 schrieb Luis Henrique B. Sousa via >>>>> swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

It seems that there is a consensus that this proposal might be a good

addition to the standard library. All comments on this thread in the
past
few weeks were related to naming, not around the behaviour or
validity of
the proposed methods. So I will submit this proposal for review very
soon
assuming that nobody else has strong arguments against it. :-)

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

If you have any corrections or suggestions to the proposal text
itself,
please comment on this gist:
nnnn-more-lenient-collections-subscripts.md · GitHub
(or pull request to my repo)

Regards,

- Luis

On Tue, May 10, 2016 at 4:13 PM, Luis Henrique B. Sousa >>>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

    Please let me know if you have more suggestions or corrections on
    this proposal.
    I'm tempted to submit it for review. :-)

    - Luis

    On Tue, May 10, 2016 at 8:53 AM, Luis Henrique B. Sousa >>>>>> <lshsousa@gmail.com <mailto:lshsousa@gmail.com>> wrote:

        It sounds good, thanks for you suggestions @Vladimir, @Patrick
        and @Brent.

        I've just updated the proposal:

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

        - Luis

        On Tue, May 10, 2016 at 6:50 AM, Vladimir.S via >>>>>> swift-evolution >>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> >>>>>> wrote:

            Yes, I feel like 'within' is much better than 'bounded'.

            How about such changes in proposal:

            a[bounded: -1 ..< 5] --> a[within: -1 ..< 5] (or
a[inside:
            -1 ..< 5] )

            a[optional: 0 ..< 5] --> a[checking: 0 ..< 5]
            a[optional: 5] --> a[checking: 5]

            ?

            On 10.05.2016 6:27, Patrick Smith via swift-evolution >>>>>> wrote:

                I like the idea of the of the bounded subscript,
however
                the optional one I
                feel could be used for clumsy code.

                .first and .last have value, but once you start
stepping
                several arbitrary
                indices in, then that code is likely fragile?

                I can think of ‘within’, ‘inside’ and ‘intersecting’
as
                alternative names
                for ‘bounded’ that attempt to explain what is going
on:

                let a = [1, 2, 3]

                a[within: 0 ..< 5] // [1, 2, 3]
                a[inside: 0 ..< 5] // [1, 2, 3]
                a[intersecting: 0 ..< 5] // [1, 2, 3]

                    On 28 Apr 2016, at 10:11 PM, Luis Henrique B.
Sousa
                    via swift-evolution
                    <swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto:swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>>> wrote:

                    As we have discussed throughout this thread, the
                    initial proposal was
                    modified to include alternative subscript methods
                    instead of modifying
                    the default operator/subscript behaviour.
                    The first draft is
                    here:

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

                    I've also put this as a gist so that you can leave
                    comments with respect
                    to the proposal document itself. Any suggestion or
                    help is very welcome.

nnnn-more-lenient-collections-subscripts.md · GitHub

                    Regards,

                    - Luis

                    On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B.
Sousa
                    <lshsousa@gmail.com <mailto:lshsousa@gmail.com>
                    <mailto:lshsousa@gmail.com

                    <mailto:lshsousa@gmail.com>>> wrote:

                        This proposal seeks to provide a safer ..<
(aka
                    half-open range
                        operator) in order to avoid **Array index out
of
                    range** errors in
                        execution time.

                        Here is my first draft for this proposal:

https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md

                        In short, doing that in Swift causes a
runtime error:

                        leta =[1,2,3]
                        letb =a[0..<5]
                        print(b)

                        > Error running code:
                        > fatal error: Array index out of range

                        The proposed solution is to slice the array
                    returning all elements
                        that are below the half-open operator, even
                    though the number of
                        elements is lesser than the ending of the
                    half-open operator. So the
                        example above would return [1,2,3].
                        We can see this very behaviour in other
                    languages, such as Python and
                        Ruby as shown in the proposal draft.

                        This would eliminate the need for
verifications
                    on the array size
                        before slicing it -- and consequently runtime
                    errors in cases when
                        the programmer didn't.

                        Viewing that it is my very first proposal, any
                    feedback will be helpful.

                        Thanks!

                        Luis Henrique Borges
                        @luishborges

                    _______________________________________________
                    swift-evolution mailing list
                    swift-evolution@swift.org
                    <mailto:swift-evolution@swift.org>
                    <mailto: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 <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

_______________________________________________

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