{"id":366,"date":"2014-07-06T08:08:13","date_gmt":"2014-07-06T14:08:13","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=366"},"modified":"2016-01-10T11:34:52","modified_gmt":"2016-01-10T17:34:52","slug":"another-look-at-function-argument-labels-in-swift","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/another-look-at-function-argument-labels-in-swift\/","title":{"rendered":"Another Look at Function Argument Labels in Swift"},"content":{"rendered":"<p><b>Update:<\/b>  This post was written in 2014 when Swift first came on to the scene.  As such it may be out of date and not applicable to Swift 2.  Proceed with caution!<\/p>\n<p>We&#8217;ve said it before and we&#8217;ll say it again:  Make everything as simple as possible, but not simpler.  Wait, no, Albert Einstein said that.  <i>We<\/i> said more descriptive code is better code, and that&#8217;s one reason we fell in love with programming in Objective-C.  This<\/p>\n<pre>\r\nconvertDegrees(50, 'C', 'R')\r\n<\/pre>\n<p>is much less readable than<\/p>\n<pre>\r\n[temperature convertDegrees:50 fromScale:\"Celsius\" toScale:\"Rankine\"]\r\n<\/pre>\n<p>Yes, you have to type more, but the resulting code is easier to read and comprehend what is going on.  Enough already with the trying to make code as compact or as short as possible!<\/p>\n<p>The good folks at Apple must have also appreciated this feature of Objective-C enough to include it in Swift.  Using <i>named parameters<\/i> you can declare functions that require argument labels in the function call.  For example:<\/p>\n<pre>\r\nfunc convertDegrees(degrees:Double, fromScale s1:TemperatureScale, toScale s2:TemperatureScale) -> Double\r\n<\/pre>\n<p>allows you to invoke the function as:<\/p>\n<pre>\r\nconvertDegrees(50, fromScale:.Celsius, toScale:.Fahrenheit)\r\n<\/pre>\n<p>Failure to include the labels in the call will result in a <code>missing argument labels<\/code> error from the Swift compiler.<\/p>\n<p>This is fine and all, but, it seems a bit annoying that when using an argument label that could be also be used as the variable name itself to have to provide some other name like <code>s1<\/code> or <code>s2<\/code>.  What would be nice is if we can require the argument label but then reuse that label as the variable name as well.  Of course this post would come to an abrupt and unfulfilling end if there weren&#8217;t a way to do that.  Fortunately there is!<\/p>\n<pre>\r\nfunc convertDegrees(degrees:Double, #fromScale:TemperatureScale, #toScale:TemperatureScale)\r\n<\/pre>\n<p>Using the <code>#<\/code> symbol you tell Swift, &#8220;I want to use this as the argument label <i>and<\/i> the variable name.&#8221;  Now rather than using <code>s1<\/code> and <code>s2<\/code> in your <code>convertDegrees<\/code> function, you can use <code>fromScale<\/code> and <code>toScale<\/code>.<\/p>\n<p>The full source code:<\/p>\n<pre>\r\nimport Foundation\r\n\r\nenum TemperatureScale {\r\n    case Fahrenheit, Celsius, Kelvin, Rankine\r\n}\r\n\r\nfunc convertDegrees(degrees:Double, #fromScale:TemperatureScale, #toScale:TemperatureScale) -> Double {\r\n\r\n    \/\/ If fromScale and toScale are the same just return degrees\r\n    if (fromScale == toScale) {\r\n        return degrees\r\n    }\r\n\r\n    \/\/ Convert to Kelvin then to our target\r\n    var kelvin:Double\r\n    switch fromScale {\r\n    case .Fahrenheit: \r\n        kelvin = (degrees + 459.67) * (5\/9)\r\n    case .Celsius: \r\n        kelvin = degrees + 273.15\r\n    case .Kelvin: \r\n        kelvin = degrees\r\n    case .Rankine: \r\n        kelvin = (degrees) * (5\/9)\r\n    }\r\n\r\n    var result:Double\r\n    switch toScale {\r\n    case .Fahrenheit:\r\n        result = (kelvin * (9\/5)) - 459.67\r\n    case .Celsius:\r\n        result = kelvin - 273.15\r\n    case .Kelvin:\r\n        result = kelvin\r\n    case .Rankine:\r\n        result = (kelvin * (9\/5))\r\n    }\r\n    return result\r\n\r\n}\r\n\r\nvar temperature = 120.0\r\nvar converted:Double\r\n\r\nconverted = convertDegrees(temperature,\r\n                           fromScale:.Celsius,\r\n                           toScale:.Fahrenheit)\r\n\r\nprintln(\"\\(temperature) Celsius is \\(converted) Fahrenheit\")\r\n<\/pre>\n<p>Astute readers will notice that our enumeration could have used the <code>String<\/code> type, and we can improve on things further and take advantage of named elements in Swift tuples as well:<\/p>\n<pre>\r\nimport Foundation\r\n\r\nenum TemperatureScale:String {\r\n    case\r\n    Fahrenheit = \"Fahrenheit\",\r\n    Celsius = \"Celsius\",\r\n    Kelvin = \"Kelvin\",\r\n    Rankine = \"Rankine\"\r\n}\r\n\r\n...\r\n\r\nprintln(\"\\(temperature.degrees) \\(temperature.scale.toRaw()) is \\(converted.degrees) \\(converted.scale.toRaw()).\")\r\n<\/pre>\n<p>Throwing in named element tuples, we can refactor our entire function to:<\/p>\n<pre>\r\nfunc convertTemperature((degrees:Double, scale:TemperatureScale), #toScale:TemperatureScale)\r\n<\/pre>\n<p>A final look:<\/p>\n<pre>\r\nimport Foundation\r\n\r\nenum TemperatureScale:String {\r\n    case\r\n    Fahrenheit = \"Fahrenheit\",\r\n    Celsius = \"Celsius\",\r\n    Kelvin = \"Kelvin\",\r\n    Rankine = \"Rankine\"\r\n}\r\n\r\nfunc convertTemperature(temperature:(degrees:Double, scale:TemperatureScale),\r\n                        #toScale:TemperatureScale) -> (degrees:Double,scale:TemperatureScale) {\r\n\r\n    \/\/ If fromScale and toScale are the same just return degrees\r\n    if (temperature.scale == toScale) {\r\n        return temperature\r\n    }\r\n\r\n    \/\/ Convert to Kelvin then to our target\r\n    var kelvin:Double\r\n    let degrees = temperature.degrees\r\n    switch temperature.scale {\r\n    case .Fahrenheit: \r\n        kelvin = (degrees + 459.67) * (5\/9)\r\n    case .Celsius: \r\n        kelvin = degrees + 273.15\r\n    case .Kelvin: \r\n        kelvin = degrees\r\n    case .Rankine: \r\n        kelvin = (degrees) * (5\/9)\r\n    }\r\n\r\n    var converted:Double\r\n    switch toScale {\r\n    case .Fahrenheit:\r\n        converted = (kelvin * (9\/5)) - 459.67\r\n    case .Celsius:\r\n        converted = kelvin - 273.15\r\n    case .Kelvin:\r\n        converted = kelvin\r\n    case .Rankine:\r\n        converted = (kelvin * (9\/5))\r\n    }\r\n    return (converted, toScale)\r\n\r\n}\r\n\r\nvar temperature:(degrees:Double,\r\n                 scale:TemperatureScale) = (120.0, .Celsius)\r\n\r\nvar converted = convertTemperature(temperature, toScale:.Fahrenheit)\r\n\r\nprintln(\"\\(temperature.degrees) \\(temperature.scale.toRaw()) is \\(converted.degrees) \\(converted.scale.toRaw()).\")\r\n\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Update: This post was written in 2014 when Swift first came on to the scene. As such it may be out of date and not applicable to Swift 2. Proceed with caution! We&#8217;ve said it before and we&#8217;ll say it again: Make everything as simple as possible, but not simpler. Wait, no, Albert Einstein said [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-366","post","type-post","status-publish","format-standard","hentry","category-swift"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/366"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=366"}],"version-history":[{"count":11,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/366\/revisions"}],"predecessor-version":[{"id":2443,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/366\/revisions\/2443"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=366"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=366"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=366"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}