var, val and Immutability

Why ‘var’ or ‘val’ at all?

TL;DR:  adding the ‘var’ (or val) is clearer than python syntax

Python programs traditionally just set variables to a value, not fuss no extra step.  Creating the variable by giving it a value uses the same syntax as setting an existing variable to a new value. Using the same syntax does come with problems, and understanding those problems, can help understand why kotlin has ‘var’ and ‘val’, and how they can help.

Firstly, a typo or misspelling can create a new variable when the intention was to set an existing variable to a new value.  But even without misspellings or typos, it can be useful when reading the code to be able to see immediately if a new variable is being created, or an existing variable reused.  Sometimes, it can get really hard to tell which is happening.

Consider this python code:


#traditional python

def outer(a):
   b = 5
   def inner1():
      return b + 3
   def inner2():
      b = 2
      return b + 3

# python with types
def outer(a:int)-> int:
    b:int = 5
    def inner1()->int:
       return b + 3
    def inner2()-> int:
       b:int = 2
       return b + 3

Function ‘inner1’ uses the variable ‘b’.  This variable comes from the scope of the function ‘outer’.  Function ‘inner2’ also uses variable ‘b’, but in this case, because there is an assignment to variable ‘b’ in that inner scope, this is a different ‘b’ from the outer scope ‘b’.  This can be quite confusing, as inner2 is similar to inner1 and it is logical to expect again the outer ‘b’ is being used.  The ‘python with types’ example does make the it clear there is a new declaration to the reader,  but only if the programmer already realises what is happening and writes the assignment to ‘b’ with the ‘:int’.   If the programmer actually wanted to, both inner1 and inner2 use the variable ‘b’ from outer scope, then a new variable is being created without the programmer knowing.  I suspect almost every python programmer who has nested functions has been tripped up at least once with this type of problem.

This potential confusion is all a consequence of the fact that in python there is no difference between declaring a variable, and reusing a variable.

fun inner2():Int{  // first version
   var b = 2
   return b + 3
}
fun inner2():Int{ // second version
   b = 2
   return b + 3
}

I left out the ‘outer’ level to draw attention to the ‘var b = 2’ vs ‘b =2’.  The first version has a new local ‘b’ (like the python with an assignment), the second version uses ‘outer’ b, even though there is an assignment.  The value of the ‘var’ is that there is a clear indication of ‘new variable’ vs ‘existing variable’.

Using types with python can help, but makes more code than with kotlin.

Python has recently allowed for the optional specification of type, kotlin requires the specification of type, but with less code than specifying type with python.  In fact in may examples, kotlin manages to be as concise as python with still specifying type. Kotlin achieves this by inferring type, and it is difficult to see how that could ever by provided in python.  The strength of python is you do not need to specify type at all. If the program is just for yourself, then exceptions if things go wrong are better than having to write extra code.  Kotlin is a language for when you write programs to be run by other people, python is perfect for when the programs are for yourself.

summary

declaring a variable can be the same as python, but with the keyword ‘var’ making it clear that this is a declaration, not the reuse of an existing variable. In python, the ‘:’ is optional, and an aid to both readability and tools like ‘mypy’, but does not change the code. In kotlin, the ‘:’ is needed when the language cannot learn the type from the value being assigned. ‘var a = 3’ is setting ‘a’ to an integer, so ‘a’ must be an integer. With ‘var a:Int = 3’, like python, the type is not needed, with ‘var a:Int? = 3’ the type is needed, because this is saying ‘a’ may be either int (as it is initially) or ‘null’.

var vs val: An new concept?

So declaring a variable can be the same as python, but with the keyword  ‘var’ making it clear that this is a declaration, not the reuse of an existing variable.  This explains ‘var’. ‘val’ declares a new variable just like ‘var’, however in this case the variable cannot be reused. The variable cannot appear on the left a future ‘=’ statement.

This is somewhat similar to simply using capitalised names in python to indicate a constant.  However, a ‘val’ just means that ‘variable’ (or value) will always reference the same object, it does not ensure that object will not change.  See immuatbility below.

Immutability

Consider in python if ‘a’ is set to a list, then the list can change and thus the value of ‘a’ change, without setting ‘a’ itself to a new value

>>> a = []
>>> b = a  # set b to same list
>>> a.append(5)  #change the list, but a is still referencing same list
>>> print(a)
[ 5 ]  # a is not the same as it was
>>> print(b)
[ 5 ]  # b is still the same list as a, so has the same change

‘a’  and ‘b’ both could be ‘val’ in kotlin as they are not assigned new values, even though the actual value they reference does change.  The change with kotlin is that there is MutableList (the equivalent of the python ‘list’) as well as the regular ‘List’ which is immutable so cannot change.

In python, all the basic types: int str bool float etc., are ‘immutable’.  I cannot reproduce the ‘side effect’ above that can happen with a ‘list’, with any of those basic types.  If I set ‘a’ to a string, then that string cannot change.  I can only set ‘a’ to new string, which will leave the orginal string unchanged.  If ‘b’ is set to ‘a’ with a string, ‘b’ will not change because while i can change which string it is that ‘a’ references, the strings themselves are immutable.

In python all basic types are immutable, but collections: lists, sets, dictionaries and their derived classes, are mutable. In kotlin each of these collection classes is immutable, but has a Mutable alternative class.

Advertisements

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s