> On Nov 29, 2016, at 1:56 PM, Joe Groff <[email protected]> wrote:
>> On Nov 29, 2016, at 1:54 PM, John McCall <[email protected]> wrote:
>> 
>> 
>>> On Nov 28, 2016, at 11:53 AM, Joe Groff <[email protected]> wrote:
>>> 
>>> 
>>>> On Nov 19, 2016, at 8:57 PM, John McCall via swift-evolution 
>>>> <[email protected]> wrote:
>>>> 
>>>>> On Nov 19, 2016, at 6:03 PM, Alan Cabrera <[email protected]> wrote:
>>>>>> On Nov 19, 2016, at 4:02 PM, John McCall <[email protected]> wrote:
>>>>>> 
>>>>>>> On Nov 19, 2016, at 3:31 PM, Alan Cabrera <[email protected]> wrote:
>>>>>>>> On Nov 19, 2016, at 1:21 PM, John McCall <[email protected]> wrote:
>>>>>>>> 
>>>>>>>>> On Nov 19, 2016, at 10:07 AM, Alan Cabrera via swift-evolution 
>>>>>>>>> <[email protected]> wrote:
>>>>>>>>>> On Nov 19, 2016, at 9:27 AM, Jean-Daniel <[email protected]> wrote:
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>>> Le 19 nov. 2016 à 15:58, Alan Cabrera via swift-evolution 
>>>>>>>>>>> <[email protected]> a écrit :
>>>>>>>>>>> 
>>>>>>>>>>> I’m not sure if this was proposed or not; or even if this is a 
>>>>>>>>>>> Swift-ly way of doing things.  It would be pretty handy to be able 
>>>>>>>>>>> to declare init() functions in my module to register handlers.  
>>>>>>>>>>> It’s a common pattern in enterprise software.
>>>>>>>>>>> 
>>>>>>>>>>> Currently, I have to generate a lot of boilerplate code to emulate 
>>>>>>>>>>> the behavior.  I think it would be cleaner to have these global 
>>>>>>>>>>> init() functions.
>>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> I’d rather like a swift attribute equivalent to : 
>>>>>>>>>> __attribute__((constructor))
>>>>>>>>>> 
>>>>>>>>>> It will not force me to call my initializer init, and moreover it 
>>>>>>>>>> will let me declare multiple functions so I would be able to 
>>>>>>>>>> register multiples handlers from a single module without having to 
>>>>>>>>>> group all the register call into a single init() function.
>>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> I’m not quite following what “__attribute__((constructor))” means; it 
>>>>>>>>> looks like an LLVM implementation bit.  Do you mean defining a new 
>>>>>>>>> Swift declaration attribute named “constructor”?  If so, I really 
>>>>>>>>> like that idea.  I think that the specific attribute name 
>>>>>>>>> “constructor” may be a bit confusing though, since it’s not really 
>>>>>>>>> constructing anything specific.  Maybe “startup” would be a more 
>>>>>>>>> descriptive attribute name?
>>>>>>>>> 
>>>>>>>>> @startup
>>>>>>>>> func registerHandlers() {
>>>>>>>>> }
>>>>>>>>> 
>>>>>>>>> The attribute would also help the compiler and IDEs prevent direct 
>>>>>>>>> calling of the startup functions, thus reinforcing/focusing the 
>>>>>>>>> startup functions’ role as global startup functions.  Maybe global 
>>>>>>>>> teardown functions would be helpful as well.
>>>>>>>>> 
>>>>>>>>> I’m going to try goofing around with the idea on my fork.
>>>>>>>> 
>>>>>>>> Some sort of reflective discovery would be better, I think.  Eager 
>>>>>>>> global initialization is superficially attractive — what could be 
>>>>>>>> simpler than just running some code at program launch? —  but as a 
>>>>>>>> program scales up and gains library dependencies, it very quickly runs 
>>>>>>>> into problems.  What if an initializer depends on another already 
>>>>>>>> having been run?  What if an initializer needs to be sensitive to the 
>>>>>>>> arguments or environment? What if an initializer need to spawn a 
>>>>>>>> thread?  What if an initializer needs to do I/O?  What if an 
>>>>>>>> initializer fails?  Global initialization also has a lot of the same 
>>>>>>>> engineering drawbacks as global state, in that once you've introduced 
>>>>>>>> a dependency on it, it's extremely hard to root that out because 
>>>>>>>> entire APIs get built around the assumption that there's no need for 
>>>>>>>> an explicit initialization/configuration/whatever step.  And it's also 
>>>>>>>> quite bad for launch performance — perhaps not important for a server, 
>>>>>>>> but important for pretty much every other kind of program — since 
>>>>>>>> every subsystem eagerly initializes itself whether it's going to be 
>>>>>>>> used or not, and that initialization generally has terrible locality.
>>>>>>> 
>>>>>>> Very good points.  I recognize the dangers.  However.
>>>>>>> 
>>>>>>> Don’t these problems already exist given that user code can still 
>>>>>>> execute at program startup?  It cannot be denied that the pattern is 
>>>>>>> used and is extremely useful though, as you point out above, it should 
>>>>>>> be used carefully.  Thinking on it, there are always pros and cons to 
>>>>>>> most language features and one relies on best practices to avoid 
>>>>>>> shooting oneself in the foot.  For each of the specters listed above, 
>>>>>>> there are simple accepted practices that can be adopted to avoid them; 
>>>>>>> most of those practices are already being employed for other situations.
>>>>>>> 
>>>>>>> And the pattern is not just useful in enterprise software.  Complex 
>>>>>>> applications’ app-delegate did-finish-launching methods are chucked 
>>>>>>> full of hand stitched roll calls to framework initialization code.  
>>>>>>> This needlessly places a brittle dependency/burden on the application 
>>>>>>> developer in what should be a simple behind the scenes collaboration.
>>>>>>> 
>>>>>>> One could argue that such a thing was never needed before.  I would 
>>>>>>> point to CocoaPods, Carthage, and the other influx of enterprise 
>>>>>>> influenced tooling and frameworks.  Today’s mobile applications are no 
>>>>>>> longer simply todo apps.  
>>>>>>> 
>>>>>>> Global init() functions are a clean solution to what engineers are 
>>>>>>> already boiler plating with static singleton code.
>>>>>> 
>>>>>> No, they aren't a clean solution for the reasons I listed.  They may be 
>>>>>> a solution you're used to using, but they're not a *clean* solution, and 
>>>>>> Swift's line against providing them is for the best.
>>>>>> 
>>>>>> I'm surprised that you keep talking about enterprise / complex 
>>>>>> applications as some sort of argument for them, because those are 
>>>>>> exactly the applications where, in my experience, global initializers 
>>>>>> completely break down as a reasonable approach.  It's the small 
>>>>>> applications that can get away with poor software engineering practices, 
>>>>>> because the accumulated maintenance/complexity/performance costs are, 
>>>>>> well, small.
>>>>> 
>>>>> It’s difficult to subscribe to the slippery slope arguments that contain 
>>>>> specters that can still afflict applications without global init 
>>>>> functions.  Any feature can be abused and it seems hyperbolic to provide 
>>>>> arguments that seems to ascribe the above problems as an inevitability 
>>>>> solely afflicting global init functions.  My and others’ experience with 
>>>>> them has been very different from yours.
>>>>> 
>>>>> With that said, I took some time to re-read your reply, after my 
>>>>> afternoon nap.  I really like the idea of some kind of reflective 
>>>>> discovery.  How would that work?  Maybe having a special @tag attribute 
>>>>> that can be searched at runtime?
>>>> 
>>>> There was another thread that mentioned this idea recently, but it would 
>>>> be reasonable to provide some way to get a P.Type for every type in the 
>>>> program that conforms to a protocol P.  This would be opt-in at the 
>>>> protocol level, because we wouldn't want to be prevented from e.g. 
>>>> stripping an unused type from the program just because it implemented 
>>>> Equatable.  There are some other complexities here, but that's the basic 
>>>> idea, and it's totally reasonable to support.
>>> 
>>> I worry that there are registration use cases for which "get all protocol 
>>> conformers" is a bit boilerplatey. For example, collecting test case 
>>> functions is a classic use case, and requiring a separate type declaration 
>>> for every case would be a bit heavyweight compared to just having each test 
>>> be a free function.
>> 
>> I agree with you, but I'm not sure that global initializers fit this 
>> use-case well either.
> 
> That wasn't what I was going for, sorry for not being clear. I more meant 
> that having another mechanism for discovering a set of declarations with a 
> common attribute across a program might be called for besides just types with 
> protocol conformances. Someone earlier in the thread suggested a @tag 
> attribute; something like that could be allowed to apply not only to types 
> but to functions as well.

Sure, that's a good point.

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

Reply via email to