> On Feb 19, 2017, at 11:22 AM, Ole Begemann <o...@oleb.net> wrote:
> 
> 
>> On 17 Feb 2017, at 01:26, Ben Cohen via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> Here is a list of commonly requested changes/enhancements to Dictionary, all 
>> of which would probably be appropriate to put together into a single 
>> evolution proposal:
>> 
>> init from/merge in a Sequence of Key/Value pairs (already raised as SE-100: 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0100-add-sequence-based-init-and-merge-to-dictionary.md
>>  
>> <https://github.com/apple/swift-evolution/blob/master/proposals/0100-add-sequence-based-init-and-merge-to-dictionary.md>).
>> make the Values view collection a MutableCollection (as in this PR: 
>> https://github.com/apple/swift-evolution/pull/555 
>> <https://github.com/apple/swift-evolution/pull/555>).
>> Add a defaulting subscript get (e.g. counts[key, default: 0] += 1 or 
>> grouped(key, default:[]].append(value)).
>> Add a group by-like init to create a Dictionary<K,[V]> from a sequence of V 
>> and a closure (V)->K.
> Out of interest, how would you implement this? Does it require a generics 
> feature that's slated for Swift 4? I tried two approaches that don't compile 
> in a current Swift 3.1 snapshot (and I'm getting a segfault with both 
> examples in a dev snapshot from 2017-02-14):
> 
> 1)
> 
> extension Dictionary {
>     // error: same-type constraint 'Value' == '[S.Iterator.Element]' is 
> recursive
>     init<S: Sequence>(values: S, groupedBy: (S.Iterator.Element) -> Key)
>         where Value == [S.Iterator.Element] {
>         ...
>         }
>     }
> }
> 
> 2)
> 
> // error: reference to generic type 'Array' requires arguments in <...>
> extension Dictionary where Value == Array {
>     init<S: Sequence>(values: S, groupedBy: (S.Iterator.Element) -> Key)
>         where S.Iterator.Element == Value.Element {
>         ...
>         }
>     }
> }
> 


Oops, looks like a bug in the same-type constraint implementation. Ought to 
work in 3.1. Minimal crasher repro:

extension Array {
  func f<S: Sequence>() 
  where Element == S.Iterator.Element? {
        
  } 
}

I’ve raised https://bugs.swift.org/browse/SR-4008

It ought to be done with the first one. For the second, you can’t constrain 
Value == Array because Array isn’t a type, needs to be Array<Something>.

As an (impractical) workaround, this compiles:

extension Dictionary {
    subscript(k: Key, default default: Value) -> Value {
        get { return self[k] ?? `default` }
        set { self[k] = newValue }
    }
}

extension Dictionary where Value: RangeReplaceableCollection {
    init<S: Sequence>(grouping values: S, by: (S.Iterator.Element) -> Key)
        where S.Iterator.Element == Value.Iterator.Element {
            self = [:]
            for x in values {
                let k = by(x)
                self[k, default: Value()].append(x)
            }
    }
}


let s = [10,20,22,30,31]
// have to explicitly type the Dictionary as a specific RRC
let d: [Int:[Int]] = Dictionary(grouping: s) { $0%10 }

print(d)


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

Reply via email to