Sent from my iPad

> On May 21, 2016, at 8:45 AM, Haravikk via swift-evolution 
> <[email protected]> wrote:
> 
> 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.

+1 to defining map abstractions in the standard library (separating read only 
from read write).  The value associatedtype should not take a position on 
optionality, allowing for maps which have a valid value for all possible keys.  
I have done similar things in other languages and found it extremely useful.  
It is not uncommon to have code that just needs to read and / or write to / 
from a map without having concern for the implementation of the map.

One issue I think we should sort out along side this is some kind of 
abstraction which allows code to use functions or user-defined types without 
regard for which it is accessing.  The map abstraction would build on this 
abstraction, allowing single argument functions to be viewed as a read only map.

One option is to allow functions to conform to protocols that only have 
subscript { get } requirements (we would probably only allow them to be 
subscripted through the protocol interface).  I think this feels like the most 
Swifty direction.

Another option is to take the path I have seen in several languages which is to 
allow overloading of the function call "operator".  I originally wanted this in 
Swift but now wonder if the first option might be a better way to accomplish 
the same goals.

-Matthew

> 
>>  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

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

Reply via email to