External Parameter Name in Swift

I was never a big fan of external parameter names in Objective-C. It leads to too much typing. Example of external parameter names in action shown in boldface below:

[[[UIAlertView alloc] initWithTitle:@"A Message"
  message: @"Hello World"
  delegate:nil
  cancelButtonTitle:@"OK"
  otherButtonTitles:nil] show];

Supporters claim that this leads to better readability. But, I disagree. I have never felt the need for this when coding in C or Java.

Needless to say that I was sad to see external parameter names repeated in Swift. To make things worse, the rules have become inconsistent. I will try to summarize the rules in this article.

For a procedural function, external parameter names are disabled by default. Hooray!

func simple(i: Int, j: Int) {
  println("i=\(i) j=\(j)")
}
simple(10, 20)

You could optionally enable external parameter names.

func simple(firstParam i: Int, secondParam j: Int) {
  println("i=\(i) j=\(j)")
}
simple(firstParam: 10, secondParam: 20)
simple(10, 20) //Compile error!

Here, firstParam is the external name and “i” is the internal name of the parameter.

If the internal name is descriptive enough and can be used as the external name, then you can use implicit external naming:

func simple(#i: Int, #j: Int) {
  println("i=\(i) j=\(j)")
}

simple(i: 10, j: 20)

The compiler allows setting external names of only some of the parameters. But, please don’t do this. It’s really not helpful:

func simple(firstParam i: Int, j: Int) {} //Please, stop!

So much for procedural functions. Let’s now have a look at class methods.

For class methods, external parameter names are mandatory for all except the first parameter. In fact, by default, compiler enables implicit external names for the second parameter onwards:

class Rect {
 var width: Int = 0
 var height: Int = 0
 
 func resize(w:Int, h:Int) {
   width = w
   height = h 
 }
}

var r = Rect()
r.resize(10, h:10)
r.resize(w:10, h:10) //Error. First parameter has no external name
r.resize(10, 10) //Error. Missing second parameter name

As a best practice, the first parameter name should be added to the method name. For example, this is much better:

func resizeWidth(width:Int, height:Int) {
 self.width = width
 self.height = height
}
var r = Rect()
r.resizeWidth(10, height:10) //Reads better

You can explicitly set the external names. This also allows you to set an external name for the first parameter:

func resize(width w:Int, height h:Int) {
 self.width = w
 self.height = h
}

var r = Rect()
r.resize(width: 10, height:10)

Please stick to one convention. If you must have an external parameter name for the first parameter, use it throughout.

The init method behaves somewhat differently. Here, compiler sets the external name for the first parameter as well.

class Rect {
  var width: Int = 0
  var height: Int = 0
 
 init(w:Int,h:Int) {
   width = w
   height = h
 }
}
var r = Rect(w:10, h:23)
var r = Rect(10, h:23) //Compiler error
var r = Rect(10, 23) //Compiler error

You can also do explicit naming.

init(width w:Int,height h:Int) {
 self.width = w
 self.height = h
}
var r = Rect(width:10, height:23)

I am sure I will get used to the conventions. So far, external parameter naming is my only peeve with this otherwise very easy to learn language.

 

Advertisements

3 thoughts on “External Parameter Name in Swift

  1. I think Apple has chosen an unnecessarily complex, inconsistent and unintuitive specification of external parameter names. With the current Swift spec, a programmer has to *remember* all those “conventions” (e.g., “for class methods, external parameter names are mandatory for all *except* the first parameter”) and hidden mechanisms. Readability of the code is reduced as well.

    One suggestion (to Apple) could be to use the following much simpler specification of external parameter names:

    1. For a procedural function, external parameter names are disabled by default. Yes – keep that one!

    2. For a procedural function, you can optionally enable external parameter names. But if you *do* enable external parameter names, you must do so for *all* parameters. This is really not a very big restriction. If you do use external parameter names, why not thinking about good external names for *all* your parameters, while you’re at it?

    3. There is no implicit external naming (or shorthand parameter names using the hash (#) symbol. Just get rid of that “feature”. It’s better to make the programmer think a bit harder about choosing good names for internal and external parameter. And if you *really* want to use the same name for the external parameter name, just write it twice. But why?

    4. For class methods, external parameter names are mandatory for *all* parameters, i.e. *including* the first oner. Having yet another a rule that requires the programmer to *remember* that Swift treats the first parameter differently from the other ones only creates confusion IMO. I can see the argument behind Apple’s choice (save writing, etc), but is it too much to ask a programmer to simply *not* add the first parameter name to the method name *and* to think a little bit harder about using a *descriptive* external parameter name for the first parameter? Shouldn’t this be the main goal in the first place? With this, the *only* way to write the ‘resize’ function from above should be this:

    func resize(width w:Int, height h:Int) {
    self.width = w
    self.height = h
    }
    var r = Rect()
    r.resize(width: 10, height:10)

    5. *Require* an external name for any parameter with a default value. Currently, Swift provides an *automatic* external name for any defaulted parameter you define, if you do not provide an external name yourself. This is yet another one of those “rules” or “hidden mechanisms” that a programmer must remember. It should be in the spirit of Swift to avoid hidden mechanisms as much as possible. With this suggestion, the only way to write the “join” function that is shown in Apple’s Swift book (p.252) should be:

    func join(string s1: String, toString s2: String, withJoiner joiner: String = ” “) -> String {
    return s1 + joiner + s2
    }

    SUMMARY:

    I believe that with modifications 1 – 5, as outlined above, external parameters names are considerably simpler to explain, use and read, while simultaneously not introducing any limitations. There shouldn’t be a laundry list of “rules to remember” or “alternative ways” to express the same thing in N different ways.

  2. I am starting to teach myself this language, and iOS/Mac development and this has been throwing me for a bit of loop. Thanks for posting this — it helped me to understand when names are required and when they aren’t.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s