Alan, The other thread subject is "Getting a list of protocol conformers"
On Sun, 20 Nov 2016 at 14:40 Alan Cabrera via swift-evolution < [email protected]> wrote: > On Nov 19, 2016, at 8:57 PM, John McCall <[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. > > > Great, are there any keywords I can use to search for this thread? > > 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. > > > Does the other thread go into detail about this? I’m not sure that I > follow why it should be opt-in as opposed to simply searching for all > implementations of a specific protocol. Is it because the protocol > information is erased after compilation? > > In general, this kind of straightforward compilation task — "compilation" > in the general sense of gathering like information from different sources — > is pretty easy to support and much less problematic than features that rely > on arbitrary code execution. > > > Agreed, it solves the bulk of the problems I would have solved with global > init functions without the temptations to indulge in dangerous proclivities. > > > Regards, > Alan > > > _______________________________________________ > 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
