CS1 in Kotlin

2021-11-21
30 min read
println("CS1 in Kotlin")
Kotlin

This semester(1) I began offering Kotlin as a language option in my CS1 course—alongside Java, which we had been using previously for many years. When I began using Kotlin three years ago, it seemed like an ideal language for teaching CS1.

And so far our experiences with it in my course have been extremely positive! Out of around 1300 enrolled students, around 20% are using Kotlin, and they are doing really well. Even with only 20% of the class using Kotlin, I suspect that this represents one of the larger current deployments of Kotlin for CS1. I’ll share how we got here, why I think Kotlin is such a great choice—particularly compared to Python and Java—and some early results from our use of Kotlin alongside Java.

Note that I wrote this in anticipation of a JetBrains education webinar that I joined as a guest. Here’s a link to my slides.

What is Kotlin?
What is Kotlin?

According to Wikipedia, Kotlin is “a cross-platform, statically typed, general-purpose programming language with type inference.”

Kotlin is designed to interoperate fully with Java, and the JVM version of Kotlin’s standard library depends on the Java Class Library, but type inference allows its syntax to be more concise. Kotlin mainly targets the JVM, but also compiles to JavaScript (for e.g. frontend web applications using React) or native code (via LLVM), e.g. for native iOS apps sharing business logic with Android apps. Language development costs are borne by JetBrains, while the Kotlin Foundation protects the Kotlin trademark.

In addition, Kotlin has also been chosen by Google as the preferred language for Android development, expanding its usage to the 12 million app developers worldwide—half of the worldwide developer community—half of who develop for Android first.

There are many great online resources for learning about Kotlin, including an official Kotlin Playground tutorials and exercises. We’re also planning on publishing our own CS1 materials for Kotlin soon, which you can preview here.

Discovering Kotlin
Discovering Kotlin

When I arrived at Illinois in Fall 2017, my first teaching assignment was as a co-instructor for CS1. I took over that course in Spring 2018, and have continued to teach it since.

When I arrived, the course was taught in Java. I do a lot of programming, and at the time was heavily involved in development projects using JavaScript, Go, and Python. But Java was a language that I hadn’t used regularly for a long time.

I was reminded of all of the things that people hate about Java. Syntax clutter. Excessive ceremony. Awkward collections. Organizational ridgity. null.

Returning again to the language with the benefit of some perspective, as I began building tools to support my course, I was reminded of all of the things that people hate about Java. Syntax clutter. Excessive ceremony. Awkward collections. Organizational ridgity. null. And when considering the language from the perspective of a beginner, tack on weaknesses like an intimidating “Hello, world!”, avoidable confusion regarding equality, a character-heavy print statement, and the uncompromising objects-first requirement(2). To me, Java just didn’t seem like a great choice for CS1.

But changing the language in CS1 is itself a herculean and dangerous task. I was new, and was doing my best to go along and get along. And Python, the other popular choice, has its own set of serious weaknesses. So I stuck it out with Java, and found a few ways around some of the languages more problematic features from a CS1 perspective. One workaround is that our interactive playgrounds support what we call snippet mode, relaxed Java syntax that supports top-level loose code and method declarations:

int addOne(int input) {
return input + 1;
}
int i = 0;
System.out.println(addOne(i));
Java

This allows us to work incrementally through the basics of imperative programming without needing to mumble away all of the normal concepts and keywords Java students encounter in just “Hello, world!”: classes (public, class), methods (main, void), arrays (String[]), and even static.

But no number of tricks would make some of the more fundamental problems with Java go away—I’m looking at you, .equals. So I kept thinking about alternatives.

As it turned out, Bill Chapman, my co-instructor my first semester teaching CS1, ended up dropping an important hint. He was the first person to suggest Kotlin, only a few weeks before retiring(3).

I had never heard of the language, and I’m not sure exactly when I began experimenting with it. But by the time I began rebuilding some of my teaching tools a few years later, in the summer of 2019, Kotlin was the language of choice. Jeed, our high-performance Java and Kotlin toolkit and playground backend, is the first large project that I began in Kotlin, and is something that we continue to use and improve today. Kotlin is now my primary development language for non-frontend tasks, and I maintain a bunch of different tools in the language—including our containerized autograder, course plugins for both Gradle and IntelliJ, our new small-problem authoring system (1, 2), a small library of basic CS1 data structures, and greenfield projects like a new polyglot playground backend(4).

As I began working in Kotlin I noticed something right away. I liked it. A lot! Kotlin bills itself as a language that “makes developers happier”. Not to be a shill, but that has actually been my experience. Minute for minute, hour for hour, day by day, I enjoy working in Kotlin a lot more than in Java, Python, TypeScript, or any other languages I use regularly.

Newer languages should be better!

Over my two-decade career as a software creator, the programming languages that I’ve used seem to just keep getting better. On one hand, that’s quite remarkable. But on the other, it’s rather unsurprising. Newer languages should be better! Not only have we learned a lot about language design, but computers have changed in quite astonishing ways. The designers of older languages like Java or Python could hardly anticipate how much faster computers would get, and so it’s hard to fault them for failing to put those capabilities to work to aid software creation.

Or, as I put it recently in an email to a student: Always bet on the future. If you’re not willing to, it’s hard to enjoy a life in technology.

Even if you’re ready to bet on the future, not everyone else is. Currently we are teaching Kotlin alongside Java in my CS1 course. Perhaps I’ll write something else at some point about the language wars that erupt whenever you want to try something new in CS1. At this point I’ll let the outcome speak for itself. I wanted to move to Kotlin, and we ended up with both Kotlin and Java. And while that might sound like a compromise, it’s a compromise that required someone (me) to do a ton of extra work to try something new while supporting the status quo. But was it worth it? Yes.

Maximizing Fun, Minimizing Frustration
Maximizing Fun, Minimizing Frustration

Obviously the fact that I happen to like Kotlin doesn’t make it a great choice for CS1. So let’s step back and consider what makes a language a good choice for introductory courses.

Choosing a good language doesn’t, by itself, create a good introductory course.

Let me start with an important point. Choosing a good language doesn’t, by itself, create a good introductory course. No programming language can make up for other more important elements of good course structure and design. A badly designed course will still be ineffective even if taught in a great language.

It’s equally true that you can teach a decent CS1 course even using a not-so-good language, since a well-designed course can at least partially overcome the weaknesses of a poor language. But this is no excuse for continuing to use languages that are hard on beginners! It frustrates me to no end to see introductory courses continue to use languages like C and C++ that represent extremely poor choices for introducing computer science to a general audience.

My approach to evaluating languages for CS1 is simple: Maximize fun, minimize frustration:

Note that, at least for beginners, fun is largely a property of what you can do with the language, while frustration is bound up in the syntax of the language and its development environment. I think that this makes sense until students get to the point where they are intrisically motivated. At this stage in my career, I find Kotlin’s elegant syntax and idioms to be inherently enjoyable, but I’m approaching projects with the attitude: I’m definitely going to build this, I’m not just not sure how. Beginners aren’t there yet.

I consider Kotlin the best choice for CS1 today because it does a great job of both maximizing fun and limiting frustration. Now, let me try to convince you. As described above, we’ll make the case for fun primarily based on what you can create with Kotlin, and the case for frustration primarily based on Kotlin’s syntax and features of the language itself. And as we go, I’ll draw out comparisons to Java and Python, which are probably the two most widely-used alternatives for CS1.

Frontend Fun
Frontend Fun

Students get excited about computer science when they can create the same things they use every day. Projects that consist entirely of command-line text interfaces or other backend components are unlikely to excite students who entered the field hoping to solve problems and change the world. Nor is it necessary or healthy for students to spend years and years “mining code deep underground”(5) before creating something that they can recognize, or demo to a parent or friend. My course has successfully used Android projects for the last several years, allowing students to build entire apps including UI design and implementation.

Kotlin is fully-supported for Android development since May 2019. All of Google’s tutorials provide both Kotlin and Java examples, with Kotlin being the default and preferred language. Not only does Kotlin allow students to learn by building real apps, but its support from Google ensures that the language is here to stay. Kotlin also has support for compiling to JavaScript, allowing it to be run in the browser and support both frontend and full-stack web development. And like Java, it can also be used to build standalone desktop apps(6).

Compared to Java, students can have as much fun in Kotlin due to Java inter-op, and even more due to Kotlin’s ability to support web frontend development. Doing any frontend development in Python requires bringing in all the rest of the web stack, requiring that students learn not only CSS and HTML, but JavaScript, an entirely separate programming language. And while data science is the new hotness—and particularly inside the university—creating graphs doesn’t quite connect to a student’s lived experience of computer science. Courses focused on data science also often do a poor job of teaching basic computer science, a topic I’ve written about before.

Minimizing Frustration: Pythonic Clarity, Java’s Type Safety
Minimizing Frustration: Pythonic Clarity, Java’s Type Safety

As many CS1 courses progressed from Java to Python, strong typing was abandoned in favor of syntactic clarity. Perhaps that was a necessary tradeoff at the time, given the limitations of Java and Python. But Kotlin type inference now gives you much of the best of both worlds: the clarity and conciseness that are particularly useful for small programming examples in CS1, but the added benefit of strong type checking to catch common mistakes and mimimize frustration.

Put another way—the compiler should be a great friend and aid to CS1 students. Unfortunately older compilers required so much syntactic noise that this got in the way of CS1 instruction. Happily, newer compilers—like most other computer software—have become more powerful and effective. Today, the small amount of additional syntax the Kotlin compiler requires from CS1 students is worth it for the kinds of mistakes it will help them identify and correct.

Let’s examine some code examples to see how Kotlin combines some of the best features of both Python and Java.

Clarity
Clarity

Kotlin is more user-friendly right out of the gate. Here is the minimal syntactically-correct “Hello, world!” in all three languages.

Java’s “Hello, world!” is positively terrifying to beginners, full of syntax clutter and unfamiliar concepts:

// Java
public class Example {
public static void main(String[] unused) {
System.out.println("Hello, world!");
}
}
Java

Even just trying to explain what System.out.println is to a beginner is daunting. The result is a lot of hand-waving and under-rug-brushing that leaves students with the sense that programming is full of arcane secret knowledge, rather that straightforward and ultimately quite comprehensible.

Both Python and Kotlin do much better:

# Python
print("Hello, world!")
Python
// Kotlin
fun main() {
println("Hello, world!")
}
Kotlin

And Kotlin also supports scripts that contain top-level code, just like Python:

// Kotlin script
println("Hello, world!")
Kotlin

Type Safety and Inference
Type Safety and Inference

But Kotlin’s clarity does not come at the cost of type safety. Compare and contrast the following examples of basic type errors in Java, Python, and Kotlin. In Java, type information is scattered everywhere, even in this simple example. But at least it works:

// Java
int x = 0;
String y = "test";
y = 10;
System.out.println(y);
Java

Python is cleaner, but at the cost of no type checking:

# Python
x = 0
y = "test"
y = 10
print(y)
Python

And yes, I am aware that newer version of Python have introduced type hints. But nobody seems to use them, at least not in the CS1 courses I’ve reviewed. I’m sure that they are coming, and that will be a great improvement! Done right, gradual typing tools like TypeScript can be pretty fantastic.

Kotlin allows us to omit types from our declarations, but can still infer variable types and examine operations properly:

// Kotlin
var x = 0
var y = "test"
y = 10
println(y)
Kotlin

I think there’s an interesting open question about whether Kotlin introductory programmers will actually learn to think more effectively about types, since their own brain has to do the type inference when reading with even simple examples above, rather than being able to rely on the type duplication that Java provides. This would be a fascinating question to examine at some point.

Equality
Equality

Now let’s discuss possibly the worst Java footgun for introductory computer science: the difference between == and .equals.

It’s reasonable to start beginners in Java working with primitive types. So when you teach them about equality, you teach them ==, which is the correct way to compare primitive types:

int i = 0;
int j = 0;
System.out.println(i == j);
Java

It’s also reasonable to have Java Strings be the first object that you discuss in CS1, since they are both useful and also the only Java object you can create with a literal:

String s = "test";
String m = "me";
System.out.println(s + m);
Java

When you introduce objects, you are careful to remind students that, when you compare two objects, you must use .equals! Yes, it’s ugly, you say. But you must. Really. Trust me. All the time! Try it.

String s = "test";
String m = "test";
System.out.println(s == m);
System.out.println(s.equals(m));
Java

%$^&! What is happening here? Unfortunately, Java also implements String interning, meaning that two String literals will also be referentially equal. Meaning that our first chance to practice with objects (String) is also a terrible source of confusion regarding equality.

Everyone knows this about Java. Everyone—except people that don’t know Java yet!

Yes, I know. Everyone knows this about Java. Everyone—except people that don’t know Java yet! I cannot tell you how many times I see students making this mistake, or variants of it. I cannot tell you how many times I’ve made this mistake myself. And yes, a decent IDE will also warn you about this, but introductory students aren’t always programming in an IDE, and sometimes it’s better for them not to.

So you can plan on fighting this particular bug all semester long. Or just use Kotlin, where == works properly, and calls .equals behind the scenes:

val s = "test"
val m = "test"
println(s == m)
Kotlin

When you actually want referential equality—and you rarely ever do in CS1—you can break out the triple-barrel:

// required to defeat String interning
val s = String("test".toCharArray())
val m = "test"
println(s === m)
Kotlin

Python also seems to work properly in this regard:

s = "test"
m = "test"
print(s == m)
Python

Containers
Containers

Things get worse for Java when using containers, such as lists, that you really want to have in CS1.

Before you can start working with lists in Java you need to discuss import and type parameters, and you’ll also need to be prepared to answer questions about the difference between interfaces (List) and their implementations (ArrayList)(7). Manipulating lists requires awkward calls to .set and .get, which clutter the code and are visually extremely distinct from the bracket notation used by arrays, even though they behave identically.

// Java
import java.util.List;
import java.util.Arrays;
List<String> list = Arrays.asList("test", "me");
list.set(0, "another");
System.out.println(list);
Java

So much for computational thinking. And as if that weren’t bad enough, Java list literals created with Arrays.asList are actually immutable by default!

import java.util.List;
import java.util.Arrays;
List<String> list = Arrays.asList("test", "me");
list.add("Oh noes"); // doesn't work
Java

Here’s the right way, which requires yet another import and more type clutter:

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
List<String> works = new ArrayList<>(Arrays.asList("test", "me"));
works.add("another");
System.out.println(works);
Java

This is one great example of a major Java footgun that primarily affects introductory programming courses. It’s rare in real code to actually want to create a list literal, since usually you’re going to populate it with data flowing in from some other part of the program. But when teaching CS1 it’s extremely common to want to create list literals, as you demonstrate to students how lists works using small examples with prepopulated data.

In contrast, Python gets this right—no imports, bracket notation:

# Python
list = ["test", "me"]
list[0] = "another"
print(list)
Python

And Kotlin does as well, particularly when working with list literals where we can utilize type inference:

// Kotlin
val list = mutableListOf("test", "me")
list[0] = "another"
println(list)
Kotlin

I actually tend to think that operator overloading is not a great language feature, since it’s easy for people to get overly excited about and start to abuse. But it’s use in Kotlin to facilitate array-like lists and maps might actually make it worth it.

null And null Safety
null And null Safety

null is both a poor idea and a common stumbling block for novice programmers. So the fact that Kotlin places so much attention on improving null safety is both great for the language and for CS1.

Kotlin also chooses a middle ground here—neither eliminating null nor allowing you to ignore it, as you can in Java, C++, Python, and pretty much every other older language. This is an ideal stance pedagogically, given that CS1 students will need to wrestle with null values in other languages for the foreseeable future. Kotlin allows you to introduce and discuss null while still enabling beginners to write null-safe code. And of course this is also another great argument for using a compiler.

Again, compare the following code in Java, Python, and Kotlin. Java lets you shoot yourself directly in the foot:

// Java
// Ready...
String s = null; // aim...
System.out.println(s.length()); // ...fire!
Java

Python isn’t much better. null by any other name is still null:

# Python
s = None
print(s.length)
Python

Kotlin’s ability to allow you to safely work with null is one of its selling points, and a great feature:

// Kotlin
// This is a non-nullable String
var s = "test"
// This will fail, since s cannot be null
s = null
// This can never fail, since s cannot be null
println(s.length)
// This declares a nullable String variable
var t: String? = null
// Kotlin won't allow me to use an unsafe call on a
// variable that could be null
println(t.length)
// But I can use a safe call, which returns null if any of // the properties encountered are null
println(t?.length)
// Chaining also works
println(t?.trim()?.length)
Kotlin

About the only place I’ve seen null-safety in Kotlin fall down is when working with maps, but that’s a fundamentally hard problem.

Classes
Classes

One way to introduce objects naturally in CS1 is to present them as a way to represent more complex data than can be stored using primitive types: a person has both a name and an age. Students can get a fair amount of mileage out of objects as records even before introducing the idea of object methods—particularly when working with data.

Kotlin’s data classes are a perfect fit for this use of objects. In only a few lines, students can be introduced to simple compound types and begin using them to store and manipulate data. At some point later data classes can easily be transitioned to classes that provide methods. Kotlin’s data classes are more convenient that Java’s very ceremony-forward classes, or Python’s classes, even incorporating recent support for Python @dataclass annotations.

Compare Java, Python, and Kotlin’s approach to create a simple class to model data—one that acts purely as a record linking multiple fields together. Java requires a ton of ceremony even to just link two values together:

// Java
public class Person {
private String name;
private int age;
Person(String setName, int setAge) {
name = setName;
age = setAge;
}
public String getName() {
return name;
}
public void setName(String setName) {
name = setName;
}
public int getAge() {
return age;
}
public void setAge(int setAge) {
age = setAge;
}
}
// Now we can (finally) write:
Person person = new Person("Geoffrey", 42);
person.setAge(person.getAge() + 1);
Java

Python is a bit better, and even more so you use recent support for data classes:

from dataclasses import dataclass
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@dataclass
class Person:
name: str
age: int
person = Person("Geoffrey", 42)
person.name = "Geoffrey Challen"
# Although it's always tempting to just abuse a dictionary...
# person = { "name": "Geoffrey", "age": 42 }
print(person)
Python

Kotlin’s primary-constructor syntax on even normal classes already eliminates almost all of Java and Python’s excessive ceremony. Data classes also come with sensible toString and copy methods, and support destructuring assignment:

data class Person(var name: String, var age: Int)
val person = Person("Geoffrey", 42)
person.age++
println(person)
val (name, age) = person
Kotlin

You want CS1 students to reach for a class when they need to work with structured data, and not be tempted to commit dictionary abuse or an even worse solution(8). Java’s classes require enormous amounts of syntactic ceremony, and top-level classes much be separated into their own file. This causes even simple record-like classes to feel like a heavyweight abstraction.

Natural Progression from Blocks to Functions to Classes
Natural Progression from Blocks to Functions to Classes

One weakness of Java and other non-pedagogical programming languages is that the minimum runnable example forces CS1 students to squint at concepts that they have not been introduced to yet. As show above, in Java if I want to print “Hello, world!” I need to wrap that in both class and method declarations.

Because Kotlin supports both scripts (.kts files) and top-level method declarations it naturally supports introducing CS1 students to programming by building up from blocks to methods to classes. Note that it shares this desirable feature with Python, so many Python examples used in CS1 should port to Kotlin easily.

We have already compared the simplest possible class between Java, Python, and Kotlin above. But also compare Java, Python, and Kotlin in the progression from loose code to functions. In Java absolutely everything has to be surrounded by unintelligible class clutter:

// Java
// Simplest possible statement
public class Simplest {
public static void main() {
System.out.println(1 + 2);
}
}
// Simplest possible function
public class Main {
// (Good luck explaining why this has to be static...)
public static int add(int x, int y) {
return x + y;
}
public static void main() {
System.out.println(add(1, 2));
}
}
Java

Python allows you to work from the ground up, seamlessly:

# Python
# Simplest possible statement
print(1 + 2)
# Simplest possible function
def add(x, y):
return x + y
print(add(1, 2))
Python

And, with support for scripts, you can do the same in syntactically-valid Kotlin:

// Kotlin
// Simplest possible statement
println(1 + 2)
// Simplest possible function. (Kotlin allows top-level functions)
fun add(x: Int, y: Int) = x + y
// Somewhat more traditionally...
fun add2(x: Int, y: Int): Int {
return x + y
}
println(add(1, 2))
println(add2(2, 3))
Kotlin

As described previously, we have used templating tricks in my CS1 course to work around Java’s limitations in this area. While this can help, it does engender some mild confusion—particularly as you begin to remove the templates and have them write more complete pieces of code. Overall it is desirable to have students writing code that is valid without requiring any magic behind the scenes.

Other Considerations
Other Considerations

In addition to being more fun than and less frustrating than Java or Python, there are several other things that make Kotlin a great choice for an introductory programming course.

Leveling the Playing Field
Leveling the Playing Field

Many CS1 courses—including mine—mix students with a variety of programming backgrounds: from no to substantial prior experience. Many incoming freshman acquired that experience through high school AP CS courses—either AP CS A or AP CS Principles. Those courses tend to be taught in Java (AP CS A) or Python (AP CS Principles).

By teaching CS1 in a language that is neither Java nor Python, we can level the playing field and provide value to students that already know some programming.

As a result, many students that do enter college CS1 with prior experience know either Java or Python. By teaching CS1 in a language that is neither Java nor Python, we can level the playing field and provide value to students that already know some programming. Learning a second language is admittedly easier than learning a first programming language, but is also definitely harder than reviewing a language that you already know.

For this reason Kotlin is a better fit for both beginners (it is more beginner-friendly for reasons outlined below) and for students with some prior experience (it is different than what they already know).

Exacerbating existing skills gaps by teaching CS1 in a language that many students already know—like Java or Python—also makes calibrating the difficulty level of CS1 more challenging. Students that already know Java may provide the instructor with a false sense that most students are following the material, when in fact they are relying on prior knowledge and true beginners are struggling. A few times in my CS1 course we’ve noticed a big experience gap in performance on a particular quiz, a sure sign that we haven’t taught a particular concept well to students that didn’t already know it, but also a sign that is very easy to miss without appropriate cohort analysis.

Kotlin is both an excellent introductory language and one that, at least for now, will be unfamiliar to most incoming students—both beginners and those with prior programming experience. This makes it an ideal choice for CS1 and a great way to address the incoming skill gap.

High Quality Online Resources
High Quality Online Resources

While all programmers benefit from good online resources, they are particularly important for CS1 students. Not only will CS1 students inevitably search for help online, but as less experienced programmers they are less able to judge the quality of the answers that they find. Given that they can also ask their course staff for help when needed, it may actually be preferable for CS1 students to not find an answer online than to find a bad one.

Modern languages just seem to have a leg up in this area—probably because they know that they are competing for fickle developers in a crowded space. But Kotlin has all of what you expect these days: attractive documentation incorporating embedded runnable code snippets, and tutorials for beginners and more advanced programmers. The quality of the code used in their documentation and examples is excellent—which is not always the case with Java.

The fact that Kotlin is both new and rapidly increasing in popularity also seems like the sweet spot for finding help on forums like StackOverflow. Searching for help for languages like C, C++, Java, JavaScript, and (increasingly) Python too often turns up ancient answers that use ugly or outdated language idioms. Searching for help with Kotlin easily yields idiomatic examples (due to its rapid increase in popularity) but the overall quality level of those examples is also high (due to Kotlin being relatively new).

JetBrains is also providing resources and systems specifically tailored to educators that should allow us to design our own Kotlin-based course while leveraging a fair amount of their infrastructure.

Support for Multiple Programming Paradigms
Support for Multiple Programming Paradigms

CS1 courses may rotate between instructors with different ideas about how to introduce students to programming. Best practices also change over time. So it is helpful to have a language that naturally supports multiple programming paradigms and styles—without having to resort to specialized libraries or approaches that violate established language norms.

At minimum Kotlin supports what seem to be the most common CS1 programming styles: imperative, object-oriented, and functional. Obviously this is because it is less opinionated than say Java (about objects-first) or Haskell (about purely functional). There are straightforward migration paths to Kotlin for CS1 courses taught in Java, Python, C, C++, and many functional languages. It’s less clear for functional languages with Scheme-like syntax, since the syntax is just so different. But the concepts should translate.

Kotlin’s syntactic flexibility also makes is a great choice for a multi-course sequence that introduces students to different programming styles along the way. You can image a first course in Kotlin that focused on imperative and object-oriented patterns, and then a second course that leverage it’s support for functional styles. Or you could flip the order! Paradigm shifts in many curricula are accomplished by switching languages, but a new language introduces a bunch of other distractors that might drown out the stylistic differences. Kotlin allows you to illustrate the differences between an iterative and functional approach to list summation within a few lines in the same language:

val numbers = listOf(1, 2, 4)
// Imperative
var sum = 0
for (i in numbers) {
sum += i
}
println(sum)
// Functional
println(numbers.reduce { it, sum -> it + sum })
Kotlin

We’ve been building out a toolchain for supporting Kotlin in our course, and as part of it we’ve developed some feature analysis tools. So it may also be possible to even enforce a functional style in Kotlin, by prohibiting looping and certain selection statements. That would be fun to try.

And, Of Course, Great Tools
And, Of Course, Great Tools

I would be remiss if I didn’t mention that JetBrains, the company that maintains Kotlin, is in the business of selling developer tools. And it shows. Kotlin support in the IntelliJ IDE is fantastic, and JetBrains seem to be launching a lot of other exciting tools as well—such as Code With Me, which we’re going to continue to evaluate for use in CS1.

Experiences with Kotlin in CS1
Experiences with Kotlin in CS1

This is fairly long already, and the semester isn’t quite over. So I’ll postpone a full examination of our experiences with Kotlin in my CS1 course for another post.

But as a brief summary, and to whet your appetite. We’ve released Kotlin alongside Java as a first-class language citizen in CS 124, my CS1 course. Students complete 70 daily lessons, all available in Java and Kotlin. In almost all cases, the topics of the Java and Kotlin lessons are the same each day, with only the languages used in the examples and on the problems being different.

The daily lessons include hundreds of interactive playgrounds along with 446 videos and interactive walkthroughs created by 17 different authors, with primary contributions from me and Colleen Lewis. Our Java materials have a two-semester head start and are still more comprehensive—1116 videos and interactive walkthroughs from 135 contributors. But our Kotlin content is catching up quickly.

We build programming proficiency through daily practice and homework problems and on weekly proctored quizzes. Our current materials include 58 practice problems, 63 graded homework problems, 37 practice quiz questions, and 36 graded quiz questions, for a total of 194 programming challenges. But this is only a subset of our full library of 480 small programming problems, created and graded using our custom problem authoring framework—which is, of course, written in Kotlin! Students also complete a multi-part Android development project, which is available in both languages.

We have 201 staff who know only Java, 13 who know only Kotlin, and 91 able to help students in both languages. And, out of 1282 current students, 259 are using Kotlin (20%) and the remainder Java. At this point the Kotlin students are doing a bit better than the Java students, overall, but I suspect that this is due to the fact that Kotlin attracted a slightly more experienced group of students.

Kotlin works for CS1!

All in all, the results are fairly easy to summarize. Kotlin works for CS1! And the fact that it already works this well, in our first semester, when we still have a lot more staff, materials, and institutional knowledge supporting Java, makes me very excited about the future.

If you would like to use Kotlin in your CS1 course, either alongside Java or on its own, I would love to help! We have all kinds of cool tools that I’d love to share with you and work on together, and the format of our materials opens up the possibility for exciting cross-institution collaborations. Please get in touch.

Thanks for reading!
I'd love to know what you think.
Feel free to get in touch.