Swift is Confused about Deverbal Nouns

Sometimes, words are both verbs, and nouns. For example, a Cheshire cat has a grin, and a Cheshire cat grins. The noun form of these words is known as deverbal.

Noun

English: cat’s grin
Swift: cat.grin

Verb

English: Cat, grin.
Swift: cat.grin()

Differentiating seems like no problem, right? The parentheses, which denote method invocation, or lack thereof, makes it clear what the equivalent English is.

To Xcode!

struct CheshireCat {
    var grin = Grin()
    func grin() {}
}
struct Grin {}

Invalid Redeclaration of 'grin()' grumpy

Look, Swift, I understand where you’re coming from. Your rationale is that there’s not a meaningful difference between

func grin() {}

and

let grin: () -> () = {}

You’re trying to stop me from confusing myself, and I appreciate the thought, but I don’t think that you’re aware that your faith in me is inconsistent.

Swift is harboring a double standard on homonyms

Swift, sometimes you let me refer to different things, using the same name. You take no issue with closures referring to overloaded functions, as long as I let you know what signature I need them to represent:

func grin() {}
func grin(grin: Grin) {}
init() {
    let grinWithExistentialVoid: () -> () = grin
    let grinWithGrin: Grin -> () = grin
}

When I clearly explain myself, you have no trouble using the appropriate homonym. You’re a smart cookie. I know you’re up to handling deverbal nouns, and I know that you’re going to let me know if use homonyms incorrectly. There’s no reason to be so overprotective. For as uncommonly as I need to do this, I can deal with the explicit typing.

Swift is still less confused than C#

As long as the methods take parameters, Swift has no problems with method names being the same as other member names. This works fine, for example:

func grin(grin: Grin) {}
let grin = Grin()

C# can’t handle it.

void Grin(Grin grin) {}
Grin Grin;

The type 'CheshireCat' already contains a definition for 'Grin'

However, C#’s extension methods provide a workaround, which is, of course, patently ridiculous, but handy nonetheless.

public static void Grin(this CheshireCat cat)

0 comment

  1. You’re trying to inspect the cat for its property of a grin.

    There are two way you can do this. You can ask the cat (cat.hasGrin()) or you can ask your eyes (light.getCat().hasGrin()) – to try to inspect the internal properties of the cat directly for its grin state requires one to be clairvoyant, which no sensible programming language should permit.

    1. Because we’re dealing with a Cheshire cat, we can be assured that it has a grin. In fact, it probably makes sense for CheshireCat.grin to be marked as unowned, as the grin may sometimes not have a cat. I’m sorry, but I’m not following “try to inspect the internal properties of the cat directly” yet.

      1. Good point. If the grin is indeed an independent entity to the cat, then it should exist as an entirely separate object. That cat’s relationship to the grin thereby becomes a loose a association.

        So we get:

        light.getGrin() – returns null or and object

        cat.getGrin() returns null or object.

        light.getCat().getGrin() returns null or object.

        1. A get accessor external to a property is not a modern construct, however. If I were using C++/Metal exclusively, I don’t believe I’d be having these property-requiring ideas.

          The accessor of cat.grin must return some Grin, which Swift can guarantee by not using an optional.

Leave a Reply

Your email address will not be published. Required fields are marked *