I think that before this can be done there needs to be an abstraction of what a 
Dictionary is, for example a Map<Key, Value> protocol. This would allow us to 
also implement the important lazy variations of what you suggest, which would 
likely be more important for very large dictionaries as dictionaries are rarely 
consumed in their entirety; in other words, calculating and storing the 
transformed value for every key/value pair is quite a performance overhead if 
only a fraction of those keys may actually be accessed. Even if you are 
consuming the whole transformed dictionary the lazy version is better since it 
doesn’t store any intermediate values, you only really want a fully transformed 
dictionary if you know the transformation is either very costly, or transformed 
values will be accessed frequently.

Anyway, long way of saying that while the specific implementation is definitely 
wanted, the complete solution requires a few extra steps which should be done 
too, as lazy computation can have big performance benefits.

That and it’d be nice to have a Map protocol in stdlib for defining other map 
types, such as trees, since these don’t require Hashable keys, but dictionaries 
do.

> On 21 May 2016, at 11:27, Honza Dvorsky via swift-evolution 
> <[email protected]> wrote:
> 
> Hello everyone,
> 
> I have added a very simple, but powerful method into a Dictionary extension 
> on multiple projects in the last weeks, so I'd like to bring up the idea of 
> adding it into the standard library, in case other people can see its 
> benefits as well.
> 
> Currently, Dictionary conforms to Collection with its Element being the tuple 
> of Key and Value. Thus transforming the Dictionary with regular map results 
> in [T], whereas I'd find it more useful to also have a method which results 
> in [Key:T].
> 
> Let me present an example of where this makes sense.
> 
> I recently used the GitHub API to crawl some information about repositories. 
> I started with just names (e.g. "/apple/swift", "/apple/llvm") and fetched a 
> JSON response for each of the repos, each returning a dictionary, which got 
> saved into one large dictionary as the end of the full operation, keyed by 
> its name, so the structure was something like
> 
> {
>   "/apple/swift": { "url":..., "size":...., "homepage":... },
>   "/apple/llvm": { "url":..., "size":...., "homepage":... },
>   ...
> }
> 
> To perform analysis, I just needed a dictionary mapping the name of the 
> repository to its size, freeing me to discard the rest of the results.
> This is where things get interesting, because you can't keep this action 
> nicely functional anymore. I had to do the following:
> 
> let repos: [String: JSON] = ...
> var sizes: [String: Int] = [:]
> for (key, value) in repos {
>   sizes[key] = value["size"].int
> }
> // use sizes...
> 
> Which isn't a huge amount of work, but it creates unnecessary mutable state 
> in your transformation pipeline (and your current scope). And I had to write 
> it enough times to justify bringing it up on this list.
> 
> I suggest we add the following method to Dictionary:
> 
> extension Dictionary {
>       public func mapValues<T>(_ transform: @noescape (Value) throws -> T) 
> rethrows -> [Key: T] {
>         var transformed: [Key: T] = [:]
>         for (key, value) in self {
>             transformed[key] = try transform(value)
>         }
>         return transformed
>     }
> }
> 
> It is modeled after Collection's `map` function, with the difference that 
>  a) only values are transformed, instead of the Key,Value tuple and 
>  b) the returned structure is a transformed Dictionary [Key:T], instead of [T]
> 
> This now allows a much nicer workflow:
> 
> let repos: [String: JSON] = ...
> var sizes = repos.mapValues { $0["size"].int }
> // use sizes...
> 
> and even multi-step transformations on Dictionaries, previously only possible 
> on Arrays, e.g. 
> var descriptionTextLengths = repos.mapValues { $0["description"].string 
> }.mapValues { $0.characters.count }
> 
> You get the idea.
> 
> What do you think? I welcome all feedback, I'd like to see if people would 
> support it before I write a proper proposal.
> 
> Thanks! :)
> Honza Dvorsky
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to