[swift-evolution] Global init() functions

Jay Abbott jay at abbott.me.uk
Sun Nov 20 11:13:33 CST 2016


The other thread subject is "Getting a list of protocol conformers"

On Sun, 20 Nov 2016 at 14:40 Alan Cabrera via swift-evolution <
swift-evolution at swift.org> wrote:

> On Nov 19, 2016, at 8:57 PM, John McCall <rjmccall at apple.com> wrote:
> On Nov 19, 2016, at 6:03 PM, Alan Cabrera <adc at toolazydogs.com> wrote:
> On Nov 19, 2016, at 4:02 PM, John McCall <rjmccall at apple.com> wrote:
> On Nov 19, 2016, at 3:31 PM, Alan Cabrera <adc at toolazydogs.com> wrote:
> On Nov 19, 2016, at 1:21 PM, John McCall <rjmccall at apple.com> wrote:
> On Nov 19, 2016, at 10:07 AM, Alan Cabrera via swift-evolution <
> swift-evolution at swift.org> wrote:
> On Nov 19, 2016, at 9:27 AM, Jean-Daniel <dev at xenonium.com> wrote:
> Le 19 nov. 2016 à 15:58, Alan Cabrera via swift-evolution <
> swift-evolution at swift.org> 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
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161120/e8eeac41/attachment.html>

More information about the swift-evolution mailing list