[swift-evolution] Optional safe subscripting for arrays

Maximilian Hünenberger m.huenenberger at me.com
Fri Feb 5 19:10:03 CST 2016


Inline:

> Am 06.02.2016 um 01:20 schrieb Andrew Bennett <cacoyi at gmail.com>:
> 
> Has it been considered to just do this:
> 
> extension CollectionType {
>     func at(index: Index) -> Generator.Element? {
>         return self.indices ~= index ? self[index] : nil
>     }
>     func update(value: Generator.Element, atIndex: Index) -> Generator.Element? {
>         guard self.indices ~= index else { return nil }
>         let oldValue = self[index]
>         self[index] = value
>         return oldValue
>     }
> }
> 
> Compare:
>      let x = array[safe: index]
>      let y = array.at(index)
> 
> It's more concise (for the getter), doesn't have to introduce new syntax, works in current swift, and it doesn't have ambiguity about nil in a subscript setter.
> 

Although it is shorter I think an additional safe index access is a small tweak of the normal index access. Therefore it should be a subscript.
Furthermore both method names don't indicate that they could fail.
Also consider this example:

        array[ifExists: 0] = array[ifExists: 1]

        // vs

        array.at(1).map{ array.update($0, atIndex: 0) }

        if let newElement = array.at(1) {
            array.update(newValue, atIndex: 0)
        }

> There's precedent for the update function in Dictionary:
>     public mutating func updateValue(value: Value, forKey key: Key) -> Value?
> 
> It would be a shame (and surprising/unsafe) to have to do this:
> 
>     array[safe: index] = .Some(nil) // stores nil

You only have to use this if "array" is of type "[Int?]" but how often do you use such a type?

>     array[safe: index] = nil        // deletes a value
> 

This doesn't delete a value. It does nothing.

- Maximilian

> 
>> On Sat, Feb 6, 2016 at 10:58 AM, Maximilian Hünenberger <swift-evolution at swift.org> wrote:
>> You are totally right. The return type is "Int??".
>> 
>> My point was that if we allowed something like this (as suggested by Dave Sweeris I think):
>> 
>>         var array: [Int?] = [1]
>>         array[ifExists: 0] = nil
>> 
>> To set the element at index 0 to nil instead of doing nothing.
>> The next example would also set index 0 to nil even though the getter failed:
>> 
>>          array[ifExists: 0] = array[ifExists: 1]
>> 
>> 
>> - Maximilian
>> 
>>> Am 05.02.2016 um 10:20 schrieb Haravikk <swift-evolution at haravikk.me>:
>>> 
>>> 
>>>>> On 4 Feb 2016, at 20:24, Maximilian Hünenberger via swift-evolution <swift-evolution at swift.org> wrote:
>>>>> 
>>>>> I just realized that the normal setter for failable lookups is very nice in case of assigning/swapping:
>>>>> 
>>>> 
>>>>> extension Array {
>>>>>     subscript(ifExists idx: Index) -> Element? {
>>>>>         get { return (startIndex ..< endIndex) ~= idx ? self[idx] : nil }
>>>>>         set { if (startIndex ..< endIndex) ~= idx && newValue != nil { self[idx] = newValue! } }
>>>>>     }
>>>>> }
>>>> 
>>>> 
>>>>         // array[index1] is only set if both indexes are valid
>>>>         array[ifExists: index1] = array[ifExists: index2] 
>>>> 
>>>> 
>>>> if array is of type [Int?] and the special setter for optional Elements would have been added:
>>>> 
>>>> array[index1] would be set to "nil" if array[index2] is nil or index2 is not valid which is unfortunate.
>>> 
>>> Wouldn’t the return type be Int?? in this case? It’s not as pretty to test for as a plain Int? but iirc you can still distinguish a return type of nil from an optional that happens to contain nil, which should allow you to tell the difference between a nil value and an invalid index, I just can’t recall how at the moment (as I design around cases like these like my life depends on it ;)
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160206/368c70b5/attachment.html>


More information about the swift-evolution mailing list