Course Review – “Programming Languages” Series on Coursera

I’m a big fan of Coursera. It offers a lot of excellent courses and specializations from very authoritative vendors like Google, IBM, Stanford, Princeton, Yale, just to name a few.

I’ve been using the platform for more than five years now, and I’ve taken more than 30 courses in a wide variety of subjects and difficulty levels. Well, admittedly, almost all of them have been quite technical covering areas like data structures and algorithms, some particular programming language, data science and machine learning, web development, etc.

A few days ago, I decided to brainstorm some potential topics for future articles. So I started looking for ideas throughout various of my sources – forums, blogs, books, and of course, online courses.

This is how I stumbled upon one of the best foundational programming courses I’ve taken. Strictly speaking, it’s not a single course, but it’s divided into three parts:

However, the instructor himself admits that the only reason the course is split this way is that it would be way too big for a single online course. Therefore, in this article, when I refer to “the course,” I would mean all the parts together.

The course is offered by the University of Washington. The instructor is Dan Grossman, who, in my opinion, is a superb teacher, and the way he ties concepts together is just awesome.

Let me give a brief overview and explain why I find this course so valuable.

Course Overview

The course represents the basic concepts that underlie all, or almost all, programming languages. It shows how these concepts fit together. You will work with three programming languages – Standard ML, Racket, and Ruby. The course has a stronger emphasis on functional programming, so no surprise that the first two languages are functional. Saying this, I’d like to highlight that the purpose of the course is not learning those three languages. As the instructor explains in the intro videos, these languages are used because of their simplicity. They allow the material to stay super focused on the important points and allow the key concepts to shine. By using multiple languages, you will be able to compare and contrast some very similar concepts and their slightly different implementations. On the other hand, there will also be cases when you see fundamentally different design approaches in different languages.

I think the course balances well between theory and practice. It teaches you how to make use of the strongest sides of a language and design correct and elegant programs. You will learn to think more deeply than purely in terms of language syntax. If you are a typical OOP guy like myself, it may help if you try to “start fresh,” not comparing what you already know with the material in the first two parts. Pattern matching and recursion will be very much the main ingredients in almost everything you will implement. This is very different from the standard object modeling that you’re probably more comfortable with. So, be prepared to rewire your brain to some extent.

From the tooling perspective – for the first part of the course, you’ll work with Emacs, which in my opinion, is also quite cool to get familiar with. If you’re coming from the Visual Studio or Rider land like myself, this will definitely broaden your perspective.

Before digging deeper, I’d like to briefly mention another excellent specialization that has some things in common with the “Programming Languages” course in terms of covered concepts. That’s the Functional Programming in Scala specialization. I will post another article about this one in the foreseeable future but, for now, I would just encourage you to embrace the challenge and plan to take both of them. Probably you will feel like your head is about to explode a few times but I guarantee you the result is very rewarding and you will not regret it. After that, the all-time classic SICP book will be a piece of cake for you! Ok, I’ve exaggerated a little here but you get the point…

Let’s now dig deeper into the Programming Languages course and what the different parts have to offer.

Part A

Part A introduces you to functional programming in a statically typed language – Standart ML. You will become a true master in recursion, pattern matching, composing and passing functions around. Then you will learn about type systems and how the compiler does the so-called type inference.

Here is a list of Part A topics that I copied from the course website:

Syntax vs. semantics vs. idioms vs. libraries vs. tools

ML basics (bindings, conditionals, records, functions)

Recursive functions and recursive types

Benefits of no mutation

Algebraic datatypes, pattern matching

Tail recursion

Higher-order functions; closures

Lexical scope

Currying

Syntactic sugar

Equivalence and effects

Parametric polymorphism and container types

Type inference

Abstract types and modules

Part B

In Part B you will be working with another functional language – Racket, which is a Lisp dialect. Racket, in contrast with ML, is a very dynamically typed language. You will compare the tradeoffs between the two, in what cases you may want the program to be rejected by the compiler early on instead of relying on runtime failures in a dynamically type setting. This ends up with probably the most challenging and rewarding homework in the whole course when you will implement your own programming language and an interpreter. Of course, the language will be simplified but on the other hand, you will implement many required features for a programming language – variables, closures, environments, function calls, etc.

Some of the Part B topics are:

Racket basics

Dynamic vs. static typing

Laziness, streams, and memoization

Implementing languages, especially higher-order functions

Macros

Eval

Part C

Part C gets you into the Object-Oriented world with Ruby. If you are quite experienced with OOP you may be tempted to skip this part. I know I was. Don’t do this. I’m sure you will benefit from the way the author explains the main OOP paradigms and evaluation rules like dynamic dispatch. He also covers topics like mixins and double dispatch. But the most interesting part, and a big punch line in the course, is at the end of Part C when you’ll see some very practical comparisons between FP and OOP and how they decompose programs in exactly the opposite way. This is something I really enjoyed and I’m sure you will too.

Here’s a list of some of the Part C topics:

Ruby basics

Object-oriented programming is dynamic dispatch

Pure object-orientation

Implementing dynamic dispatch

Multiple inheritance, interfaces, and mixins

OOP vs. functional decomposition and extensibility

Subtyping for records, functions, and objects

Class-based subtyping

Subtyping

Subtyping vs. parametric polymorphism; bounded polymorphism

Recommended Background

This course is definitely not for the absolute beginner. But on the other hand, it’s not really advanced neither. If you’ve done some programming for a couple of years, even if not professionally, you should be good to go. For example, if you have some basic idea of the following concepts you would most probably be a good fit for the course:

Variables, conditionals, loops, arrays

Recursion (just very basic understanding)

Implementation vs abstraction/modularity

Some basic data structures: arrays, linked lists, binary trees

No matter how experienced you are, you will almost certainly struggle with some of the assignments. Don’t let that discourage you. Be consistent and you will be very well rewarded for your determination at the end.

Homework Assignments

There is good and bad news here. The good news is that you will practice and learn a lot from the homework assignments. The bad news is that sometimes it may feed a little frustrating. This is because you will be restricted to a single homework submission per day. This means that you should be very confident in your solution and you have a very solid suite of unit tests. I’m sure you’ve seen courses where you can submit your solution how many times you want. This effectively pushes you to use the auto grader as a trial & error approach. So you get an error, you change something small somewhere and you submit again hoping the error goes away. This course is not like that. You should be quite confident in what you wrote, otherwise you’ll have to wait until the next day.

There is also a code review part. After you pass the programming assignment you will get a sheet with the answers and the correct solutions. Then you will review three of your classmates’ solutions. Your solution will also be reviewed. This doesn’t influence a lot your final score but I find it quite helpful and interesting to see the solutions other people are coming up with.

Price

The course has a free and a paid version. I personally took the paid one, so I can’t really tell whether the free version has anything missing other than the final certificate. Generally, certificates from online programs like this one are still not perceived as something super valuable from a career development perspective but I think it surely doesn’t harm to have one. Also, the value you get is pretty good for the price they offer, which is:

Part A: 36€

Part B: 27€

Part C: 26€

Total Time to Complete

The instructor suggests it takes between 100 and 200 hours to complete the course. Of course, this greatly depends on the student, prior knowledge, the time he can spend on the class weekly. Speaking for myself, with a full-time job, I could hardly put more than 10 hours per week. I think it took me around three months to complete the course. So, generally, I think the 100-200 range is a pretty good estimate.

The “Clash of Styles” Series

Based on some of the key takeaways in the course, I’ve written a series of articles comparing OOP and FP from a very practical standpoint.

Some of the topics covered:

The Operations Matrix, or how FP and OOP have a completely diametrical perspective on the same set of requirements.

Implementation by rows/variants – OOP style.

Implementat by columns/operations – FP style.

How do FP and OOP affect the Extensibility/Maintainability of your system?

The Open-Closed Principle from OOP and FP perspectives.

Double Dispatch, or when it’s time to abandon OOP and replace it with a more convenient Functional solution.

The Visitor Pattern – how does it fill some of the gaps between FP and OOP.

Summary

That was everything I had to say about this remarkable course. I hope you try it out and enjoy it to the same extent that I did. After that, I’ll be very happy to hear your opinion. So don’t hesitate to drop me a note with your impressions.

If you decide to go with the paid version of the course, you can do that via the links in this article. This is how I will receive a commission. Of course, this is totally up to you. In any case – enjoy the course!

Thanks for reading!