Why I don't like implicit self. in classes

So, I just spent a bunch of time trying to figure out what was going on with an NSView subclass whose keyDown() method wasn't doing what it was supposed to be doing. As usual, the Swift debugger was out to lunch, so I put a print at the beginning of my method just to see if the thing was firing at all:


override func keyDown(event: NSEvent) {
    print ("WHY IS THIS NOT GETTING CALLED")
   
    ...
}


Sure enough, the log never showed up in the console, which suggested that my method wasn't being called, and also, when I typed any key, the Print dialog was opening up, suggesting that the key event was getting mangled into the system thinking it was a ⌘P key event. Well, a bunch of event dispatch debugging later, I facepalmed when I realized what was going on:

NSView declares an IBAction method called print(), with its Sender argument as an AnyObject.

My attempt to call the system "print" function resulted in calling self.print() instead, because the Swift compiler thinks it's just too **** hard to just type the self. when you want to call an instance method or get a property.

Grr.

Amen.


I also don't like the implicit type declarations. When you see


foo = bar


in the code, what is the type of foo? Is it a local variable, property, or ??? I prefer explicit typing and use of self.propertyName for properties and methods. Call me Crusty.

This wouldn't be a problem if we didn't have useless global functions.

Are you implying that the print() function is useless?

That's not what I meant, but yes, I guess that's also true! 😉


Global functions do not make any sense. Who are you asking to execute them? The computer? That's the wrong level of abstraction for a language like Swift.


Console.Write almost makes sense: "Console, write this." is wrong (Write implies that we're writing to the console, and if that were the case, the method would be a method on the programmer, not the console), but Console.Display(something) would work.


C# 6 solves the problem of having class name clutter.


I don't believe there's a reason to have both static classes and namespaces, but Swift needs to adopt one of those concepts, or something like it, to sort out its name collision problems.

I think they're suggesting that this is only a problem because not all functions are scoped to types. If you disallow implicit self, then unqualified names (i.e ident and not self.ident) are either locally or globally scoped, making it easy to determine what you're referring to. The other option is to keep implicit self and eliminate globals, forcing all functions to be scoped to a type. This way, when you see an unqualified name, it has to be either local or scoped to self, which would again make it easy to determine what you're referring to. It's the combination of globals and implicit self that creates the confusion, not either on its own.

I like the way it works now. Optional self helps reduce the clutter and make source code more concise. If you customize fonts and colors of the source code display in Xcode to clearly distinguish system/framework stuff from your own source code, you won't have this problem. For me, setting all of the "Other Function/Type/..." to italic on a retina display works very well. It is unfortunate that by default they use identical fonts/colors.

It may make it (marginally) more concise, but it makes it substantially less clear.


Relying on IDE syntax coloring as a Band-Aid around ambiguity in the language design isn't a satisfying solution, either, especially if you are colorblind.

Log a bug if the colors aren't good enough; they're not actually as good as any of us need, for optimal help, but Apple may not know it yet.

What I'm saying is that I'm colorblind, so even if the colors were completely excellent, they're not as helpful for me as they would be for you. I'd prefer a well-designed syntax for the language itself.

So you currently think, but we haven't experienced a programming language that wasn't meant to be represented by text alone. Apple cares about people like you; you should help them do better, because what makes things good for you makes them great for those who have more cone types. Surely we can't believe that colored text represents the best that programming technology can offer…

Sure, requiring self here would have prevented this particular issue. However, it does add a lot of noise to code in the usual case where you don't conflict with the standard library (I suspect if NSView had been designed today, this method wouldn't be called print). It also wouldn't help with all the other cases in Swift where the names of functions and methods and variables can be either shadowed or overloaded. Practically speaking, at some point you're going to need to rely on an IDE feature to disambiguate names, and this is currently one of those cases.


Given the tradeoffs, I don't personally want explicit self. If I said that in all cases things had to be prefixed by their module name, Swift.print(…) and Swift.Int, etc, to avoid conflicts between modules then you would probably agree that goes too far. So I think this is a continuum that everyone will be picking their own location on.


The most useful action at this point is to file a bug report to get the name of that method on NSView changed when it is imported into Swift, because that's obviously going to be a high frequency issue for people no matter what they think about explicit self. Then you could try to get explicit self required for everyone in Swift, or perhaps settle for an optional compiler warning setting that would allow you to enforce its use in your own codebase.

It seems like a "simple" solution to audit all Cocoa classes for names that conflict with standard library names, and change one or the other. Or at least provide a compiler warning if a conflict is detected.


Swift continues to be haunted by decades of Cocoa. Given the complexity, they work remarkably well together, but there's no denying Cocoa's legacy is holding Swift back in numerous ways from being the clean, modern language it wants to be. I just had to make a whole bunch of Swift classes NSObject subclasses, just so I could use them in a table view, which makes me sad.

Why sad from inheriting from the correct class?

When a class derives from NSObject, it gets the objc runtime heaped in automatically.

This is a good example, but i'd still prefer implicit self. Theres nothing stopping you from explicitly using self, is there?

Why I don't like implicit self. in classes
 
 
Q