[swift-evolution] [Pitch] Add `mapValues` method to Dictionary
Honza Dvorsky
jan.dvorsky at me.com
Sun May 22 04:47:59 CDT 2016
Please correct me if I'm off here, but I quickly looked at the
implementation of lazy collections/sequences, and I think it's because the
goal is to keep the API of e.g. normal Array and a lazy Array the same, so
that you don't actually have to know which one you're working with. But
under the hood, they're very different objects, as one owns the memory of
its elements, whereas the lazy one goes back to the array it was created
with and pulls it elements (before e.g. transforming them). And as structs
cannot be subclassed, a lot of the functionality is implemented in default
functions on the protocol. So if you wanted to create a lazy version of a
Dictionary, which has an identical API, you'd have to duplicate a lot of
code - unless you pull the Dictionary-ness into a protocol, make Dictionary
just the normal form of Dictionary, but allow a LazyDictionary under the
hood to pull values from a parent dictionary based on keys, transform them
with mapValues and return them.
Does that make sense? I looked at the implementation of Dictionary in the
stdlib yesterday, and IMO it'd be a pretty huge amount of work to refactor
it into the Map protocol first, so I'm trying to push for having a non-lazy
version done first, and then add the lazy version once someone proposes to
add the Map protocol later (otherwise this'll just get stuck here for
months, because I doubt the core team would be happy with making such large
changes for allowing one convenience method only, now that Swift 3 is being
stabilized).
On Sun, May 22, 2016 at 7:48 AM Dan Appel <dan.appel00 at gmail.com> wrote:
> I don't understand - why do we need a map protocol for a lazy mapvalues?
> On Sat, May 21, 2016 at 11:12 PM Brent Royal-Gordon <
> brent at architechies.com> wrote:
>
>> > Obviously if it's required to have a lazy variant for all collection
>> methods, I'd probably pull back this proposal, as it would automatically be
>> rejected by the core team.
>>
>> I'm not a member of the core team, but I doubt it's necessary.
>>
>> I don't think it makes much sense to wait for a lazy implementation. If
>> there *is* going to be a Map protocol, then the best way to implement it
>> will require an advanced generics feature that's still in the proposal
>> stages:
>>
>> // Note: I'm simplifying signatures here.
>>
>> protocol Map: Collection {
>> associatedtype Key
>> associatedtype Value
>> associatedtype Iterator: IteratorProtocol where
>> Iterator.Element == (Key, Value)
>>
>> subscript (key: Key) -> Value? { get }
>> func mapValues<T>(transform: Value -> T) -> [Key: T]
>> }
>>
>> And implementing the laziness will similarly work best with not only that
>> feature, but also conditional conformances:
>>
>> protocol LazyMap: Map, LazyCollectionProtocol {
>> subscript (key: Base.Key) -> Base.Value? { get }
>> func mapValues<T>(transform: Value -> T)(…) ->
>> LazyMappedValuesMap<Base, T>
>> }
>>
>> extension LazyCollection: LazyMap where Base: Map {
>> …
>> }
>>
>> struct LazyMapValuesMap<Base: Map, NewValue>: Map {
>> …
>> }
>>
>> If we *don't* wait, on the other hand, we're going to end up in
>> manual-specification and GYB hell. (And even then, I believe conditional
>> conformances are not enough to force all LazyCollectionProtocol conformers
>> to support Map if they have a Map base. You'd need conditional *conformance
>> requirements*, which are *not* planned because it's not safe to add a
>> requirement to a protocol.)
>>
>> I just don't think laziness is so crucial that we should stop the presses
>> until we have it. `mapValues` carries water all by itself, even without a
>> matching `lazy.mapValues`.
>>
>> --
>> Brent Royal-Gordon
>> Architechies
>>
>> --
> Dan Appel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160522/6b828c1b/attachment.html>
More information about the swift-evolution
mailing list