> 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. -Joe _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
