Swift for Beans – var, let and Type Inference

I have always preferred explicitly typed languages, saving a couple of characters by simply declaring a variable as var or let can quickly end up in a game of “Guess who?” or “what” to be more precise.

Its straight forward enough with immediate assignments or when the expected type is clear.

var name = "Foo"  //clearly String
var street = customer.street //most likely String
var customer = Customer(name: "Foo", ...)

However when dealing with complex domain models or business functions with unclear return type the value of strong typing quickly becomes apparent.

var value = contract.amount  //Int/UInt/Float/Double/String/...?
var customer = contract.customer //String/domain model Customer/...?
var amountDue = billingService.calculate(...)  //Int/UInt/Float/Double/...?

Swift is still a statically typed language, it employees type inference to define the type of variables and constants. Hence once a type has been inferred, the variable cannot be reused later on for a different type.

var foo = "foo"
foo = true  //compiler error

ERROR at line 58, col 7: cannot assign value of type 'Bool' to type 'String'
foo = true 
      ^~~~

This is very similar to what has been proposed in JEP 286: Local-Variable Type Inference for Java 9. Citing complaints about unnecessary boilerplate code as a core reason.

Swift also allows “type annotation” of variables and constants. Having worked with Java for so many years, I feel far more comfortable when the types are defined explicitly, giving that extra bit of contextual information.

var value: Int = contract.amount  //Int  
var customer: Customer = contract.customer //Customer type 
var result: Double? = billingService.calculate(...)  //returns an optional Double

In Swift constants are defined with let. The value of the constant does not have to be known at compile time, but may not be changed after assignment.

let answer: Int = 42
answer = 42 + 8 //results in compilation error  

This is equivalent to final in Java. This is one point where the verbosity of Java becomes a disadvantage. Consider the code example below, using constants with final makes the code clearer and allows for compile time checking.

private final String id;

public void foo(final String bar) {
    final String barCap = bar.toUpperCase();
    String output = "FOO";
    output += barCap;
    ...
}

Yet most of the time the final key word is omitted, I am as guilty of this as anyone else.

When comparing the same code in Swift the first thing you notice is that the parameter doesn’t have a modifier. Unlike Java parameters are constant by default.

func foo(bar: String) {
    let barLC = bar.uppercased()  //without type annotation
    var output = "FOO"
    output += barLC
    ...
}

It is much more common to find constants in Swift code then in Java code, its quite surprising that a couple of characters can lead to an entirely different coding style.

This was a quick look at Swift variable, constants and Type Inference, the next post will have a look at Swifts data types from classes, structures, tuples to enums.

Further Resources:
JEP 286: Local-Variable Type Inference (Java 9 Proposal)
Types and Type Inference (SWIFT)
Swift – The Basics

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.