In preparation for an upper level class that I’m teaching this semester, I spent the summer writing my first app entirely in Swift. (It’s 7 Second Diet, a meal-tracking app that’s not a pain in the tuchus to use. Edit: Nevermind, this app is now defunc. Sorry) After spending some quality time with Swift, I realized how much I want to use Swift to teach introduction to computer science.
Choosing a language
Introduction to computer science is a unique class because most students that enroll in it don't know if they like computer science or not. As a result, a good intro class does two things: it teaches students the fundamentals of computer science and helps students learn to love computer science. Many of our department's best majors originally took intro to get their quantitate credit and never left because it was their favorite class. So, when choosing a language for intro, it’s important to pick a one that will:
- Be intricate enough to cover the core computer science concepts
- Be robust enough that students can use it for years worth of assignments
- Be easy enough that students can start programming within one week
- Be powerful enough that students can make real applications by the end of the first semester
Why Swift
Currently, most departments teach intro in C, C++, Python, or Java. Java is probably the most popular and Python is probably the second most popular. (Our primary language is Java, but we teach some intro classes in Python.) A few other schools will use languages like JavaScript, C#, Smalltalk, Haskell, or Lisp. Every language has its pros can cons and rather than giving you a giant spreadsheet of how each language stacks against Swift, I want to give you a few examples of where Swift really shines in an intro class.
First day, real code.
One trait that Python and Swift both share is that on the first day of class I can type:
print("Hello World")
and everyone in the class immediately understands this code. In Java, when I type:
package playground;
public class Starter {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
everyone's eyes glaze over and they think to themselves "what in the hell is going on here?" With Java, C, and C++, you have to spend the first month of class telling students "ignore this" because even simple programs have a lot of syntax overhead. This wastes time and causes some students to discount computer science because "it makes no sense."
Begone useless syntax.
This is a moment that will happen sometime in the next two weeks. A student will wave me over to her computer with a question about how to fix her broken Java code. When I get to her computer, I'll immediately point to a line of code and state "You are missing a semicolon here." The student then swears, "I worked on this for a F!CKING HOUR." I commiserate and then turn to her neighbor who has exactly the same issue (but he's been working on it for TWO hours). It's fun to look like a technopath, but both students wasted their time on silly mistakes. For experts, missing a semicolon is annoying. For intro students, that's their Japanese assignment. Swift still has syntax the students will need to know, but they've dramatically reduced the amount of "useless" syntax that can trip up students.
Types, optional but not forgotten.
Possibly my favorite thing in Swift is "optional types." For those who haven't worked with Swift, an optional type is exactly the same as a normal type, except it can have the additional value of nil
, which represents "no value." I love optional types because they allow me to write algorithms that behave correctly but occasionally don't return a value. For example, suppose you wanted to find the smallest number in a list of integers. If the list is empty, what value should you return? Should you return 0
? Should you throw an exception? Should you return MAX_INT
? None of those are correct. Optionals let the students write the algorithm as intended: if the list is empty, return nil
.
Algorithms first, Objects second.
Many professors who teach Java like teaching "objects first." The idea behind "objects first" is that students should learn object-oriented programming first and learn algorithmic reasoning second. I do not like "objects first." Explaining why I don't like "objects first" is a post unto itself. So, I'm going to brief here: object-oriented programming is a tool in algorithmic reasoning. It's better to learn algorithmic reasons first so you can understand why object-oriented programming is necessary.
"Objects first" is a popular technique for teaching Java because (almost) everything in Java is an object. So, to do anything interesting in Java either you have to teach "objects first" or you have to give students a library to hide the object-oriented programming until later in the semester. Either way is messy.
On the other hand, object-oriented programming is a core concept in computer science and needs to be taught to students in their first semester. So any language that doesn't use object-oriented programming (e.g., C) is a bad choice for an intro language.
Because code can live inside or outside of classes in Python, Swift, and C++, these languages making teaching introduction to computer science a lot less messy.
Named parameters, a life sentence.
Most intro students understand the basics of algorithmic reasoning before they enroll. Where they have difficulty is formalizing an algorithm so that it can run on a computer. The technique I teach them is to write an English description of what you want to happen and then transform it into code where your nouns are represented by variables and verbs are represented by functions. Named parameters make this tranformation cleaner because they allow functions to be more verbose. If you haven't used named parameters before, the easiest way to explain them is to see an example.
Suppose that you wrote a function that took two lists of integers as parameters and returned the smallest element in the first list of integers that wasn't included in the second list. Without named parameters, you would call the method like so:
x = findSmallestElementNotIn([20,30,55,22,11,34], [100,23,45,11,20,-4])
With named parameters you would write:
x = findSmallestElement(in: [20,30,55,22,11,34], notIn: [100,23,45,11,20,-4])
The named parameters are the "in:
" and "notIn:
" included with the parameters. If you had more parameters, then each would have a name as well. By including names with each parameter, the code clearly reads like a sentence:
"Set x
to be the smallest element in the list [20,30,55,22,11,34]
that is not in [100,23,45,11,20,-4]
"
Named parameters make the transformation from English to code much easier. Also, when combined with an IDE that has good autocomplete functionality, students can write better code faster.
Your references must be strong to survive.
If you know a C programmer and you ask her about Java programmers fresh out of college, then you will hear the following sentence:
"Ugh, kids today just don't understand how memory is managed. I asked him to write malloc
and he looked at me like I was speaking Greek."
Possibly the biggest problem with Java and Python as first languages is that they obscure memory management. For the types of programs you write in intro, this isn't bad. However, once you start writing larger programs that need good memory performance it becomes important.
For those who haven't used Java or Python before, those two languages are at one end of the "memory management continuum." In these languages, you never explicitly delete a memory reference. Java and Python run "garbage collection" routines that remove memory when they are no longer necessary. On the other end, C and C++ require developers to explicitly destroy memory allocations. Swift uses a technique called Automatic Reference Counting (ARC) that lives in the middle. Under ARC, developers do not explicitly destroy objects but instead must correctly organize their memory references and classify them as "strong," "weak," or "unowned" so that they can be automatically destroyed without needing to run an additional memory management process. While ARC doesn't require developers to directly manage memory, it helps students learn how to organize memory and think about how objects are stored in memory without harassing them about the details. (Students should still learn explicit memory management, just not in their first year.)
Where Swift could improve.
With Swift 2.0 coming out soon, most of my complaints about Swift are going away. That being said my biggest complaint about Swift is that it lacks Python's simple input()
and read()
commands. (If you haven't use Python before: input()
prompts the user for an input and returns a string, and read()
will take the contents from a file and return it as a string.) Having access to simple user/file input dramatically expands the set of examples and assignments I can present in the first month of intro. I can work around this by providing students with a library that would include my implementation of these two methods. The downside is that now I'm teaching the students my code and not a technique they can apply outside of the classroom. While this would work, it isn't ideal.
Why don't I use Swift this year?
Even though I think Swift is ideally suited for intro, for the next year at least, I'll be using Java in my classes. Why?
The AP test is in Java. This is the biggest reason. Each year we have several students who took high school computer science, got a 4 or 5 on the AP, and want to skip the first semester. We want to make sure they can do that without taking summer school. Because we want students to have the same language for their entire first year, if we use Swift, then those students can't skip the first semester.
Language in flux. Given how much change has happened in Swift during the past year, I'm hesitant to teach intro students how to program in a language that could have changing syntax.
No Windows IDE, yet. The fact that Swift is now open source is wonderful. I look forward to the day when we have great a IDE on Windows. That isn't the case right now. While we have Macs in our labs, students like working at home and they don't all have Apple laptops. Even if some projects have to be built on lab computers, we'd like to be as flexible as possible.
This isn't a a decision I can make by myself. Every class in computer science builds off of the last class. So, if we change our intro language, then nearly every other class in our department will need to change as well. Just because I'm excited about Swift for intro doesn't mean it's the best decision for our department. Every year we revaluate how we teach and how we can better serve our students. I expect that this year we'll have a lot of great discussions about the pros and cons of Swift, Java, and Python.
Conclusion
I could go on describing the advantages of Swift and Xcode in an intro class for a long time (the ease of use Interface Builder, the use of let
make constants a first class principal...) but this has gone on long enough. Ultimately, I want to use Swift as the language in introduction to computer science because it allows me to teach all the key concept I want to teach; it is easy enough that students can start using it on day one; it's sufficiently strict that it keeps students in line so they won't make (as many) stupid mistakes; and it's powerful enough that students can use it for the next decade without a problem. While I'm not going to teach introduction to computer science with Swift right now, I am ecstatic about the future of Swift and the impact it will have on future computer scientists.