Lists, Dictionaries Iterations & More

Python uses dictionary, list and tuple to hold collections information, with set also available but not quite as common.

Kotlin tends provides List and Maps and their mutable forms, MutableList and MutableMap as the main solutions for collections.  Again, Set and MutableSet are available matching the python ‘set’.  ‘List’ is equivalent to python ‘tuple’, MutableList to python ‘list’ and MutableMap to python ‘dictionary’.  In kotlin, there are many other options, some inherited from java, but they all have a logical role:

tuple -> List, Pair, data class

The python tuple is an immutable list, and the simple ability to use tuples  has a special role in the language with any expression with a comma creating a tuple.

Background: The good and bad of the ubiquetous python tuple

The good and bad of tuples can be seen in this :

>>> a, b = 1, 2
>>> a, b = b, a
>>> a, b
(2, 1)

The good is that tuples have almost zero syntactic overhead, all you need is a ‘,’ (comma). The bad is that it can be confusing when there is tuple, as opposed to another use of a ‘,’ in python.  Note that on the left of the assignment, it looks like a tuple, but the left of an assignment is special syntax and not a tuple.  While a tuple can hold values, it cannot hold names.  So construct like the one below

>>> a, b = 1, 2
>>> my_tuple = a, b
>>> *(my_tuple), = 6, 7
>>> a, b  # see, a and b are not changed
(1, 2)

Does not assign to a name that does not appear on the left of the assignment. In this case the ‘,’  is not indicating a tuple, but indicating ‘destructured assignment’.  Not every ‘,’  in python indicates a tuple even though a comma alone may indicate a tuple.  The comma syntax being brief is very useful most of the time, but can lead to some quirks as to whether a ‘,’ means a tuple or has another use.

>>> a = 3
>>> type(a)
<class 'int'>
>>> a = 3,
>>> type(a) #just one comma and a is tuple
<class 'tuple'>
>>> def test(a):
       print(type(a)
>>> test(1,) # does the comma mean a tuple or not?
<class 'int'>
>>> test((1)) # add brackets to make a tuple?
<class 'int'>
>>> test((1,),) # finally, now we have a single parameter that is a tuple
<class 'tuple'>

coding python tuples in kotlin

Kotlin List is close to a direct replacement for tuple, but unlike tuples and lists in python, there is no special syntax with using special brackets. “:List” for the type, “listOf()” to instance the list.

var (a1,b1) = listOf(1,2) // destructured assign a1 = 1, b1 = 2
var (a2,b2) = Pair(1,2)  // alternative destructured assign
data class XY(val x:Int, val y:Int)
var (a3,b3) = XY(1,2)  // destructured assign using data class

Note the ‘listOf() syntax to create a literal, but type is ‘List’ in a declaration.

Even in a declaration, a list can be used as a ‘drop in replacement’ for a tuple.  The syntax of declaring from a list is not as brief as python, and is not really within the kotlin ‘idiom’ to use List for a destrutured declaration.

In reality, a destructured declaration is a clear indicator that each element of the data is distinct in nature, and not really a collection.  The most common alternative to a data class in kotlin for destructured declarations are the ‘Pair’ or ‘Triple’, which are actually data classes, but without usage specific property names.

So while List is a direct equivalent to tuple, consider Pair or even a data class as the best substitute depending on the usage.

list -> MutableList

The python list can also be used in situations that are not really usage as a collection, but this tends to occur less than with lists. If there are the indexes to the list are literals, or the items in the list are not all of the same type, then consider if the list should be replaced by something other than a MutableList.  A true collection will be indexed mostly within loops. Use ‘mutableListOf() to instance a MutableList type.

common list operations:

val myList = mutableListOf(1,2) // myList cannot be reassigned, but list is mutable
val added = myList.add(33)  // add the value 3 to the (end of the) list
//  not 'add' return true if successful
myList.add(1,55) // insert into list at index 1 (2nd location)
//  list is now 1,55,2,33
remove(55)  // first the first entry matching 55 and remove (return true if successful)
val popped = removeAt(2) // remove the value found at index 2 and return that value

dictionary -> Map or MutableMap (or data class)

The direct replacement for dictionary is the MutableMap, but with no python equivalent to the Map, dictionaries are often used as maps.  If the dictionary is declared with literal values in place, then a Map (declared as mapOf( key to value) ) will be the replacement.  If the dictionary is declared empty, then a MutableMap ( declared with mutableMap() )  is likely to be the substitute.   Take care that dictionaries with literals strings for keys a probably really object substitutes and best replaced by a data class.

Common map operations.

val myMap = mutableMapOf<String,Int>()
//declared an empty map, type cannot be inferred without data
myMap.keys()
myMap.values()
myMap.toList()  // equivalent to python .items()

‘*’ and **

In python, any iterable can be used to provide parameters to a function.  Any dictionary can be used to provide keyword arguments.  kotlin has the concept of ‘varag’ which can have values provided by the ‘*’ prefix to an iterable, just as with python.  However, there is currently no equivalent to the ‘**”.  (more notes to be added on the * to be added)

list comprehension and other iterations vs map, filter, reduce

Python added map, filter and reduce together with lambda around 1994 , and then list comprehensions around 2000 with python 2.0. In that link Guido (creator of python)  presents strong arguments for list comprehensions, but notes that some people have suggested limitations to python lambda syntax is part of why in python comprehensions are favoured.  An argument is also presented on performance advantages, which in reality applies to python, but not to languages such as kotlin where compilation can support inline functions and other optimizations. It such languages, efficiencies depend on the compiler, not the technique itself.

Iterations vs map filter reduce, in both performance and appeal, is an argument that comes down to implementation details and personal taste.  Python has much stronger implementation of iterations in terms of both performance and appeal.  Kotlin has a map implementation with more performance than python list comprehensions,  but appeal is a personal choice.  Clearly, kotlin has better lambda than python, and that gives better map and filter, but comparing kotlin map and filter to the preferred python technique of iterations, cannot objectively produce a winner.   Just take the move from iterations in python to map and filter in kotlin with an open mind.

# first python
new_list = [map_func(it) for it in old_list]
//now kotlin
val newList = oldList.map{ mapFunc(it) }
#python for squaring list
new_list = [it * it for it in old_list]
//and kotlin
val new_list = oldList.map{ it*it }

# now version filtering out odd numbers
new_list = [it * it for it in old_list if it % 2 == 0]
//kotlin
newList = oldList.filter{ it % 2 == 0 }.map{ it*it }

With kotlin, a more complex, multi statement expression is possible with resorting to a ‘mapFunc’  (an external function to calculate the new value), but the two systems are similar.

Python added tuple and dictionary comprehension in python 2.7 in around 2012. Tuple comprehensions are basically identical to list comprehensions but with round brackets in place of square brackets.  In kotlin, map syntax is unchanged between immutableList (python list equivalent) and List (python tuple equivalent).

When the code is clearly cleaner for python is for a dictionary comprehension.  Starting with a map to produce a new map is case I have yet to find clean kotlin code for:

#python
new_dict = {k + '2': v * 2 for k, v in old_dict.items()}
// kotlin
val newMap = oldMap.toList().associateBy({it.first+"2"},{it.second*2})

There is more optimised code for mapping the values of a map, or mapping the keys, but mapping both at once, as you can see from above, is a little clumsy.  There may be a cleaner solution, but if so, I have not yet found it.

Sets

Sets are largely the same in both languages, with kotlin once again adding an immutable variant. Sets are not used as substitutes for other things, and the uses of a set are generally the same in both languages.  Common set operations:

val mySet = mutableSetOf<Int>()
mySet.add(3) // add value 3 to set

Arrays.

Lists, Maps and Sets, as well as data class objects, are all object stored as described in variables and objects page as having a reference stored in static (or stack) memory to an object in dynamic memory.  The ultimate in flexibility, but not the ultimate in performance.

Arrays are effectively an alternative to a List.  Fixed in size, and constructed in place. This fixed sized list, has storage of data directly in static memory, at the expense of flexibility.  For Arrays of basic types, think of allocating a block of memory to hold a fixed number items of the basic type.  If there are 10 four byte integers, then 40 bytes is required, and each integer can be addressed directly with no lookup required.  For other types, the static memory will be a block of reference to each object in dynamic memory.

In addition to efficiency, Arrays also allow interoperability with Java programs which make use of these data structures.  I will return to this section, but for now, these are features which have no direct equivalence in python.

Advertisements

Data Classes: Alternative to ‘Faux Collections’?

In coding solutions to problems, the choice of how to store the data can be between objects and lists and dictionaries.   Kotlin data classes can change which is the best choice.  This page examines just how tuples, dictionaries and lists can be used as for a ‘faux class’, and when to drop the ‘faux class’

Page contents(TL;DR – the kotlin solution):

The ‘struct’ problem: precursor to class?

The ‘c’ language has the concept ‘struct’, which is container for related, but not homogenous data.  Consider the following information about a person:

  • first name
  • last name
  • age
  • city

As long as the age is key in string form, ‘c’ could keep this information as an ‘array’ of 4 strings, referring to last name as ‘person[1]’ is far from ideal and there is that problem of needing to keep age as a string.   The struct provides an improved solution with descriptive names for the elements and types for each individudal field within the struct.  In c structs can be passed by value (which means copied) as will as by reference, comparison, ‘toString’ or other functions all have to be built separately.   The real lesson here is that every possible data type has a set of required methods.  In essence:  all data is an object.

Java: forced class hypocrisy

Java is a strange mixture.  The language designed at a time that Object Oriented programming was seen as the ‘magic bullet’ to end all problems in programming. C++ provided objects bolted on to the language ‘C’,  but java sought to have ‘pure’ object oriented programs,  but got the message wrong and decide ‘pure object oriented’ meant all code must be in classes, and missed that ‘all data is an object’.  The result is a language that is not really object oriented, but forces all code to be part of an object, even thought implementation of java does not even follow this edict itself.

Background: “one obvious solution” as a barrier object oriented programing in python.

Python itself started out with an underlying structure very object oriented, but allowing a procedural style for code written in python.   Python appears to follow the plan that beginner programmers can embrace a procedural style and allows for code to be procedural, often hiding object oriented underpinnings using procedural ‘syntactic sugar.

Programmers can learn python with no concept of OOP, then later learn OOP as they advance.  The language concentrates on ‘one obvious way to code’, requires that things done in a procedural method for learners,  should still appear procedural at all times. If you want one obvious way to solve a problem and the language allows a solution without OOP, then at least conceptually, an object oriented solution is not that one way.

In python, allowing beginners to code solutions without using objects, usually means allowing solutions substituting list, tuples, named tuples and dictionaries for data which might ideally be represented as ‘struct’ or objects.

In contrast, there has been no real work in the language to make it attractive to solve simple data requirements using classes.  Would this provide more than one logical way to solve a problem?  So data as an object remains still hard work. To start a useful object,  an ‘__init__’, method, a ‘__str__’ method and an __repr__ method are all required just for basic functionality. Contrast this with named tuples, where all is done automatically!

The result is a language that allows those who have not learnt object oriented concepts to progress as far as possible without ever declaring a class. Learning classes can wait, and all although code is built using a language with great object oriented foundations,  ‘faux objects’ built around collections (list, typles, dictionaries) are prevalent in python code.

‘faux collections’: python objects that appear as collections to the programmer.

But list, tuple, namedtuple and dictionary all can be used to describe data which is not really a collection. Used to pretend that objects which are not collections are collections. The danger to programming is to forget that these ‘faux collections’ are not really collections.  The ‘named tuple’, where each item in the ‘collection’ has its own name, is inherently designed for use purely as a ‘faux collection’.

List, tuple, named tuple and dictionary types are all described as collections. The concept of a collection is that all members of the collection are the same in nature.  But it is possible to use these types very effectively to describe things which are not really collections at all.  Consider some data read from a file to describe some people.  Each line of the file has ‘first name’, ‘last name’, age, and city.

So two lines of the file might be:

  • bill, smith, 23, new york
  • tom jones, 21, san Francisco

This file represents a true collection of ‘people’ because each line holds data which is the same in nature.  The first person or the ‘nth’ person are all people.  Every element in the collection has in common that it is a person.  But what do ‘first name’ and ‘age’ have in common?  The ‘collection’ of ‘first name’, ‘last name’, ‘age’ and ‘city’ can be held in a collection, but this is a ‘faux collection’.

In python:

people = []
while open("names") as lines:
for line in lines:
people.append(line.split(',"))

Would generate a list of people, but each person would be a list, where person[0] is the first name, person[1] is the last name etc.   So each line is using a collection for what really would be better as an object.  We could have a dictionary for each person so that person[‘first_name’] == ‘bill’ for our first person, and this may be more self documenting than person[0].

Python even gives named tuples, and each ‘person’ could a named tuple.

>>> from collections import namedtuple
>>> Person=namedtuple("Person", "first_name last_name age city")
>>> person=Person("bill","smith",19,"new york")
>>> person
Person(first_name='bill', last_name='smith', age=19, city='new york')
>>> person.age
19

The named tuple works exactly like a class, with the limitation all values are immutable. Like the ‘c’ struct, again the elements have a name, but there are more methods like ‘toString()’ already available.

A frequent request with python is for a ‘named list’, mirroring ‘named tuple’ to work just like a regular class.  But why not just make a class?  The reason is that a class definition requires a lot more code, with an __init__ and an __str__ and a __repr__ increasing the one or two lines required to declare our named tuple into around around 11 lines of code!

The kotlin solution: data classes

Consider this alternative to representing the ‘person’ from the previous section as a list, dictionary, tuple or named tuple.

data class Person(var first_name:String, var last_name:String, var age:Int, var city:String)

In one line we can define a class with a ‘constructor’ (equivalent to python __init__) a toString(), and even an equals comparator and a ‘toHash’. Using ‘val’ in place of var reproduces the ‘namedtuple’, but as used above it delivers on the request for a ‘namedlist’.  The python ‘namedtuple’ is really an class definition substitute, but in kotlin we can have an actual class just as easily.  This ease of use of a class makes many of the uses of dictionaries, lists and tuples in python redundant, and keeps the use of the kotlin equivalents to actually being used specifically for collections, and not the ‘object substitutes’ that usage that often occurs in python.

Lambdas: what do you mean I will use them?

Python has lambdas, but with python, the lambda is a very reduced lambda that Guido even hesitated about calling lambda.  I would suggest that with python, almost everything that can be done using lambdas, will be easier to understand if rewritten without the lambda.

Main Points of the page:

Background

Moving from python to kotlin in regards to lambdas, is not about the simple change in syntax. A major consequence of the syntax change is that lambdas play a greatly expanded role in programs written in the kotlin idiom. As the full power of kotlin lambdas becomes clear, a whole new tool in coding is revealed.

This page reviews lambdas, explains why they limited and usually undesirable in python but not limited and highly desirable in kotlin. TL:DR: read the headings and cherry pick reading which sections to read.

Ok, what is a lambda again?

Basically, lambdas are a ‘literal code’.  Imagine if you could not use literals in function calls or expressions, and instead literals have to be defined in a special ‘literal’ statement. The ‘hello world’ program would become:

lit greeting: "Hello World"
print(greeting)

simple code would get longer:

#this code would no longer be legal
people = 3
ears = people * 2

#instead we would have this
lit people: 3
lit doubler: 2
ears = people * doubler

Now it could be argued that by forcing our literals to have names, the code becomes more self documented. But it could be that the role of  “hello world” is no clearer by having it named ‘greeting’ and it could even be that naming ‘2’ doubler actual is confusing rather than helpful.  Note that while the declaration of ‘people’ can no longer use a general expression, this change has little real impact.

While with strings and integers forcing a special declaration and not allowing literals just seems silly, without lambdas, code literals are always moved to a special declaration. Here is an example in python declaring code with the special ‘def’ syntax, and also in the same way any other variable is declared by using a lambda.

def last_name(full_name_string):
     return full_name_string.split()[-1]
last_name_2 = last_name
last_lambda = lambda x: x.split()[-1]

>>> last_name("bill smith")
'smith'
>>> last_name2("fred bloggs")
'bloggs'
>>> last_lambda("tom jones")
'jones'

This is not an example of the real use of lambdas, but to illustrate how a ‘def’ is just giving a name to a block of code.  All three variables reference functions that work exactly the same.  But to define ‘last_name’, the ‘def’ syntax was used.  It may not even seem obvious that the ‘def’ was simply defining a variable ‘last_name’ and giving it the value of a block of code. Once defined, ‘last_name’ works like any other variable, only the definition requires a special syntax.  In contrast ‘last_lambda’ is defined like any other variable, direct from the code.  The lambda code works just like a literal for code, allowing use of code anywhere.

The above example may help with understanding, but it not the case where ‘code literals’ are needed.   In the example with numeric literals, forcing a declaration to have a special syntax did not really increase the code needed  ( syntax of ‘lit people: 3’  vs ‘people = 3’).  It was not being able to use a literal mid statement that resulted in more code.

ears = people * 2
# with no literals in an expression became
lit doubler: 2
ears = people * doubler

This is what happens with code without lambdas.  A forced declaration (using ‘def’) in place simply inserting the code where it is needed. It is where ‘code literals’ can be used mid expression that lambdas are really useful.

Simple example Use of Python Lambdas

def last_name(full_name_string):
  return full_name_string.split()[-1]
>>> my_list = ["bill smith", "fred blogs", "tom jones"]
>>> sorted(my_list, key=last_name)
['fred blogs', 'tom jones', 'bill smith']
>>> sorted(mylist, key=lambda full_name_string: full_name_string.split()[-1])
['fred blogs', 'tom jones', 'bill smith']

This is an example of the real use of lambdas.  This code takes a list of strings that are initially sorted alphabetically using the overall string, which results in sorting by first name, and re-sorts the list and returns the same list sorted by last name.

The code contrasts using a ‘def’ to define the code block, with of course gives the block of code a name and assigns it to a variable, with the lambda form where the code is a ‘literal’ within the call to sorted. Certainly the lambda saves declaring the function and saves two lines of code. The lambda also keeps the code definition where it is used, but not everyone will find things that readable.

Limitations of Python Lambdas

Kotlin Lambdas can inherit from a target environment, python Lambdas cannot.

Consider the use of kotlin in dsls like kotlinx.html.  The DSL (domain specific language) is built using lambdas.  The lambdas of the DSL can have their own language, because they have access to an enclosing environment.  In addition to the variables and methods of the enclosing scope of the lambda, there can be an entire additional vocabulary from a target environment.  There is no parallel to this in python, and the power comes from the combination of lambdas and extension functions. Consider this code:

class TestEnv(){
    var envVar = 3
    fun testInEnv(func: TestEnv.()->Unit){
        func()
    }
    fun envDoubler(value: Int) = value * 2
}
fun main(args: Array<String>){
    val test = TestEnv()
    val newNum = 4
    test.testInEnv ({ envVar = envDoubler(newNum) })
}

The lambda code can set ‘envVar’ in the target environment to a new value, and use the ‘envDoubler’ method for the calculation. This is simplistic example to keep the sample code concise, but imagine a class with an embedded file or socket connection and the power of allowing lambda code to access that file or socket. Providing access to an additional environment revolutionises the power of lambdas in many way other than enabling DSLs.

Significant whitespace is great, but it killed the lambda.

Lambdas in python are just clumsy.  I love the significant whitespace of python. It ensures easy to read code, and solves the ‘balancing braces’ challenge of other languages.  But it is hard to escape the fact a good lambda syntax and significant whitespace are difficult to combine.

Python blocks Rule! (But don’t do lambdas)

The rules for a block in python is that a block can follow any python line that ends with a ‘:’.   A block is indented from the line above, and ends when the line following the block is no longer indented.

To write a block in a ‘braces language’ like kotlin, most blocks will need a dedicated line following the block to just the closing brace.  Without this extra ‘}’ line the code is less readable.  In python a cleanly written minimal ‘block’ requires no additional lines, only one line for line of code in the block.   The code is always readable without decisions by the programmer to make the code readable, and the code simple requires one less line.

These extra lines can add up and make code longer, and it is easy to get the indenting wrong making the code hard to read. Winner: python.

Python syntax: python blocks kill the lambda

With lambda, you need to place a block in the middle of an expression, and you just cannot do that with a conventional python block.  So python has a custom syntax, where the lambda code is limited to just one expression, and unlike every other ‘:’ in python, a block cannot follow the ‘:’ in a lambda.  The syntax is

lambda :

Reasons to avoid lambdas in python:

    • A def is often more readable
    • Multi statement blocks are not even possible using lambdas
    • List iterations (and dict and tuple iterations) replace some of the most common lambda usecases

No ‘like lambda to the…’ jokes here! The result is that python lambdas are crippled.

Introducing Kotlin Lambdas.

The approach in Kotlin is to make lambdas, or “code literals” as easy as using String literals or Int literals. In fact even the “hello world” can have a lambda added.

fun main(args: Array<String>){
   println({"hello world"}())
}

The block ‘{ “hello world” }’ acts as a simple lambda function that returns the string hello world.  If you try this without the () brackets, it will print “() -> kotlin.String” indicating a function that returns a string.

So creating a lambda is as simple as creating a code block.

However, most useful lambda functions will need at least one argument.  Below are two examples of the previous ‘last name’ sort.

val lst = listOf("bill smith", "fred blogs", "tom jones")

// first ....no 'shortcuts' used, the long way
lst.sortedBy({fullName -> fullName.split(" ").last()})
[ fred blogs, tom jones, bill smith ]

// now...the preferred way
lst.sortedBy{it.split(" ").last()}
[ fred blogs, tom jones, bill smith ]

Note that at the start of the block we can give names to the parameters ” fullName ->” is declaring the parameter as “fullName”.  The block then proceeds as any other block.  There is no limit to how many statements in the block, nor on having constructs such as “if” or “when” or loops within the block.  The final statement executed in the block declares the return value.

The ‘preferred way’ example, has two changes from the first ‘no shortcuts’ solution. Consider these two sentences in English, “I am looking for the correct key, is the correct key long?  And is the correct key also grey?”   Now consider “I am looking for the correct key, is it long? And is it also grey?”   Repeating the name when what we are talking about is not necessary and the name can be replaced by “it”.  Kotlin takes the same approach. Instead of the “lastName ->” to give a name to what we are talking about, the parameter can just be called “it” during our block.  So the “lastName ->” at the beginning of the block can be omitted and when in place of ‘lastName.split(” “)’ the code just has ‘it.split(” “)’. Like in English, ‘it’ should only be clear when it is obvious what we mean by “it”, but using “it” is then often preferable to the longer way of saying what we mean.

So, firstly, omitting the parameter declaration gives the parameter a name of ‘it’ by default, reducing the clutter for simple lambdas such as this.

Next the brackets, ( ), around the parameter list to ‘sortedBy’ have been omitted. In place of ‘({it.split(” “)}), the code has simply ‘{it.split(” “)}.

This is actually the result of two separate rules which are designed to make lambdas more readable.  Firstly, the lambdas can follow the parameter list, to avoid needing to have brackets around the code.  This become most important when function calls are nested.  Secondly, if a function with lamda values as parameters would otherwise have an empty paramter list, then the brackets may be ommitted. See the following:

// first ....no 'shortcuts' used, the long way
lst.sortedBy({lastName -> lastName.split(" ").last()})

// next step use 'it' to save an actual name for parameter
lst.sortedBy({ it.split(" ").last() })

// and now we can have our lambda move after the parameter list for 'sortedBy'
lst.sortedBy(){ it.split(" ").last()}

// finally, sortedBy now has an empty parameter list () ..so the () can be omitted
lst.sortedBy{ it.split(" ").last() }

.

Conclusion.

Kotlin allows for extremely powerful lambdas, with no limitation to a single expression, as well as very concise and highly readable lambda code.  This changes how problems are solved by making lambdas a far more important part of solutions in the idiom of the language.

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.

Null Safety

 

To java programmers, ‘Null Safety’ can sound like the ‘Holy Grail’. To python programmers, ‘Null Safety’ can sound like solving a problem they never had. Truth is, the ‘null’ (or None) problem is still there for python programs, but the problem arises as a very varied problems, no the single.  Python has ‘None’ which is in many ways more like the kotlin ‘Unit’ with no actual ‘none’.

Python with types.

Consider the python code in the previous section, where the first line reads “a: int”.  This code is at best, a little strange in any language as it says “the variable called ‘a’ will be an int, but currently has no value”. How can an ‘int’ have no value? The reality is in python we could set our variable to ‘None’ to indicate it has no value, but then ‘None’ is not an int ‘type(None)’.  So to set this new variable to ‘None’ in python, it needs to a be “int or None” and to write that in python (which is very new for python)  we would need “a: Union[int, None]”.  Far easier to simply give a value to our new variable, as the code does with ‘b’.  Line 2, “b:int = 6” declares ‘b’ and sets ‘b’ to 6. Simple in both languages.  So now we have learnt that the lines:

a = None # python, the usual way!
a: Union[int, None] #python with types
var a: Int? // kotlin

Are all the same.  The first example is typical python.  The second line is python using types, (as technically could be a:Optional[int] – but the union is perhaps more self explanatory), and the third option is kotlin. In kotlin,  “Int?” is saying the python “either int or None”, but in kotlin.   The kotlin code is nice, but almost all current python code would simply set the variable ‘a’ to ‘None’, and not bother declaring the types. In python, normally the programmer just has to remember “I am using ‘a’ as int, but it could be a None”.  The programmer themselves has to remember ‘a’ could be None.

So far, kotlin has made a nicer way to say something most python code does not bother to say.  Yes, it is a good idea to document in some way that this ‘a’ should be an ‘int’, but beware it can also be None, and the kotlin is probably a better way to document what is happening, but how does this help?

Null safety is that not only have we documented that our variable can be “None” or “null”,  but that the language can help us avoid getting errors.  Kotlin does this by making it super each to check for ‘null’ and reminds us to check if we have forgotten.  This can avoid many a program error.

mem2.pngConsider a diagram similar to the background diagram of variables. In kotlin, ‘a’ is pointing nowhere, while in python ‘a’ would be pointing to the ‘None’ object. But in either case, if we try and use ‘a’ as an integer, we will get an exception.

We could, for example, in a specific situation wish to print ‘a’,  but in that situation with to use 10 for the cases where ‘a’ is ‘None’.  The code would be:

print(a if a is not None else 10) # puts what we are printing first ...but!
# or ....
print(10 if a is None else a)	# python and shorter

println(a ?: 10)  // kotlin

The kotlin is very readable, and we get a warning if we forget to deal with ‘null’ (or None). Even the shorter  python version is longer than the kotlin code, and neither python version is ideal. The shorter version hides that we are normally printing (‘a’) and the longer version has a messy ‘not None else’ but still tells the story better than the shorter code. But the main point is that if we forget that ‘a’ could be ‘None’, then this is only discovered in testing, and then only if we remember to test that case. Kotlin reminds us automatically that ‘a’ could be null, and ensures the code encounters no problem.

One more example:

a = None # for python 3.6 could use "a:Union(str, None) = None"
.... (some code that might set a, but might leave not set)
print(0 if a is None else len(a))  # python
a: String? = null
......(some code that might set a to a new string)
println(a?.length ?: 0)  // kotlin

Again kotlin will ensure we deal with the possibility that ‘a’ is null and will prevent code that could break at run time, plus it makes that code very easy to write.

The end result is that it becomes far easier, and safer, to code solutions where ‘null’ represents ‘has no real value at this time’.  An important technique becomes easier to use, and safe when it is used.