Tutorial: Using Generics

Generics allow us to specify what type is in a container.

What are Generics?

In computer programming, we often want to create a class that generically specifies an algorithm. For example, we may want to create a list of objects, like a list of people in a phone book. Or, we may want to create a list of numbers, integers, or anything else. There are at least two ways we could accomplish this: 1) we could create separate implementations of our list for each data type (e.g., one for numbers, one for integers), or 2) we could create a "generic" class. Let us take the first case, a list of numbers or integers.

class List
     action Add(integer item)
          //add our list item
     end

     action Main
          output "I made a non-generic list class with integers"
     end
end

Our implementation would be identical for numbers, except that the type changes, like so:

class List
     action Add(number item)
          //add our list item
     end

     action Main
          output "I made a non-generic list class with numbers"
     end
end

Quorum provides a mechanism to do this generically, without needing separate implementations. Then, our list could compute whatever it needs, without worrying about what kind of object is placed into it. To do this, we must first declare our new generic list class as so:

class List<Type>
     action Add(Type item)
          //add our list item
     end

     action RemoveFromFront returns Type
          //do remove operation
          //we need to say "return val" where val is of our generic Type
          return undefined
     end

     action Main
          output "This is a Generic List"
     end
end

The syntax here is complicated and requires some explanation. Notably, we define our class here normally, first with the word class and then with the word List. This is followed by angle brackets and an arbitrary word, in this case Type. Now, Type here could be any word, similar to a variable, except that this word is used as a flag by Quorum for how we can later use our list. Specifically, when our code is compiled, Quorum keeps track of how a particular generic is used (e.g., an integer, number) and adapts accordingly. In our Add and Remove actions, notice that instead of returning an individual number or integer, we now return Type. To speed along the implementation of the list, we will now use the finished and built in List class in Quorum. To use it, our code looks like this:

use Libraries.Containers.List
List<integer> list
list:Add(1)
list:Add(2)
list:Add(3)
integer a = list:RemoveFromFront()
integer b = list:RemoveFromFront()
integer c = list:RemoveFromFront()
output a
output b
output c

Like before, using angle brackets tells our list what kind it is. In this case, we are using integers. Next, we are then adding and then removing items from the list, outputting each in turn. No doubt, generics are an advanced topic in programming. They might seem esoteric, but there is some evidence in the scholarly literature that they can be helpful to programmers. For those that would like to see the completed list, the source for Quorum can be found here:

The List class in Quorum

For those that want more information on the impact of generics on programmers, here are two references that contain evidence:

  1. Michael Hoppe and Stefan Hanenberg. 2013. Do developers benefit from generic types?: an empirical comparison of generic and raw types in java. SIGPLAN Not. 48, 10 (October 2013), 457-474. DOI=http://dx.doi.org/10.1145/2544173.2509528
  2. Parnin, C., Bird, C. & Murphy-Hill, E. Empir Software Eng (2013) 18: 1047. doi:10.1007/s10664-012-9236-6

Next Tutorial

In the next tutorial, we will discuss auto-boxing, which describes how to automatically convert between primitives and objects.