Hi Jordan,

Bertrand (ex-Apple) would sometimes say during API design that “easy things 
things should be easy, and hard things should be possible”.

I don’t think you guys need to go out of your way to make the autogenerated 
1000-case enum scenario “easy". If people are clever enough to do that, then 
they can surely handle the fallout of this change. :-)

Dave


> On Oct 12, 2017, at 18:38, Jordan Rose via swift-dev <swift-dev@swift.org> 
> wrote:
> 
> Our worry when discussing it was that someone might have an autogenerated 
> 1000-case enum, and passing an entire page worth of resolved symbols might 
> not be worth it.
> 
> (It is of course questionable for someone to have an autogenerated 1000-case 
> enum as part of their binary interface, and then for someone to try to switch 
> over it. But matching against one or two of the cases shouldn't be as 
> expensive as matching against all 1000 known cases.)
> 
> Jordan
> 
>> On Oct 12, 2017, at 15:20, Greg Titus <g...@omnigroup.com 
>> <mailto:g...@omnigroup.com>> wrote:
>> 
>> I like Joe’s idea here, with the extension that the client should have just 
>> one of these arrays that contains all the symbols that it knows about at the 
>> time it was compiled:
>> 
>> I.e. in the client:
>> 
>> static myKnownOpaqueEnumCases = [MyOpaqueEnum.intCase, 
>> MyOpaqueEnum.middleCase, MyOpaqueEnum.stringCase];
>> 
>> switch indexForMyOpaqueEnumTag(&myOpaqueEnum, myKnownOpaqueEnumCases) {
>> case 0: //…
>> case 2: //…
>> default: //...
>> }
>> 
>> This optimizes for space in the client, because you have one array instead 
>> of one per potentially-different-sets-of-cases switch, but more importantly 
>> this allows for an optimization inside indexForMyOpaqueEnumTag(). If the 
>> count of the array passed in from the client is equal to the count of all 
>> known cases in the callee, then you can immediately return the internal enum 
>> tag value instead of performing a binary search.
>> 
>> (If the client expects cases that the callee doesn’t have, the link would 
>> have failed for a missing symbol, if the callee has more cases the count 
>> won’t match, so if the count is equal the cases in both object files have to 
>> be identical.) This returns the common runtime case (when the client is up 
>> to date with the callee) to being O(1).
>> 
>> The cost being, if you don’t take that fast path, maybe you have a few more 
>> entries in the cases array to binary search over than that particular switch 
>> statement needed.
>> 
>> - Greg
>> 
>>> On Oct 12, 2017, at 2:25 PM, Jordan Rose <jordan_r...@apple.com 
>>> <mailto:jordan_r...@apple.com>> wrote:
>>> 
>>> So, an update! This came up while I was talking to members of the core 
>>> team, and ChrisL felt very strongly that restricting reordering of enum 
>>> elements was a no-go, since it would be the only part of the language that 
>>> worked this way (even if it only mattered for binary frameworks). Ted also 
>>> rightly pointed out that any such language-level restriction would have to 
>>> be reviewed by the core team.
>>> 
>>> So where does that leave us?
>>> 
>>> - The naive implementation is to turn a switch into an if-else chain, 
>>> unfortunately requiring one function call per case to match.
>>> 
>>> - A slightly more complex solution keeps a single 'getMyOpaqueEnumTag' 
>>> entry point (see original email), but exposes symbols for every tag. The 
>>> values of the symbols would be kept in alphabetical order, which allows the 
>>> generated code to do a binary search over the cases they care about. This 
>>> still means N symbols, but a switch that involves several of them doesn't 
>>> necessarily have to take linear time.
>>> 
>>> - Joe Groff came up with this idea that also involves sorted symbols:
>>> 
>>> switch indexForMyOpaqueEnumTag(&myOpaqueEnum, [MyOpaqueEnum.intCase, 
>>> MyOpaqueEnum.stringCase]) {
>>> case 0:
>>>   var payload: Int
>>>   getMyOpaqueEnumPayload(&myOpaqueEnum, MyOpaqueEnum.intCase, &payload)
>>>   doSomething(payload)
>>> case 1:
>>>   var payload: String
>>>   getMyOpaqueEnumPayload(&myOpaqueEnum, MyOpaqueEnum.stringCase, &payload)
>>>   doSomethingElse(payload)
>>> default:
>>>   print("unknown case")
>>> }
>>> 
>>> In this example, the actual tag values for 'intCase' and 'stringCase' might 
>>> not be 0 and 1, but 'indexForMyOpaqueEnumTag' can do the binary search to 
>>> find out which enum we're asking for. Like the previous solution, you only 
>>> have to check the cases you care about, but this time the binary search is 
>>> in the callee, rather than the client.
>>> 
>>> - Use availability ordering, plus some kind of explicit annotation for when 
>>> multiple cases are added within the same release. (In this thread people 
>>> have suggested dates, ad-hoc sub-version numbers, and plain integer values.)
>>> 
>>> I appreciate everyone's creativity with solving the availability ordering 
>>> problem, but I don't want to tie us to a checker that will tell you if you 
>>> screw up or a history scraper that will implicitly add the right 
>>> annotations. (I don't think those are bad ideas, but they're a whole extra 
>>> pile of work on top of the main implementation!) That leaves explicit 
>>> annotations of some kind, and that leaves us in a worse place than 
>>> Objective-C. Which is permitted, but not desirable.
>>> 
>>>  At this point in time I think the second option is the best one we have: 
>>> it's relatively simple to implement, it supports everything Objective-C 
>>> does, and it doesn't make the availability model even more complicated. It 
>>> is going to be less efficient than actually knowing the case numbers at 
>>> compile time, though. Still, as Slava's pointed out, we can still change 
>>> this after we go ABI-stable; doing something more efficient will just be 
>>> limited based on deployment target.
>>> 
>>> Jordan
>>> 
>> 
> 
> _______________________________________________
> swift-dev mailing list
> swift-dev@swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev

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

Reply via email to