Learning by experimenting (with Scheme)

In his beautiful essay, The Art of Lisp & Writing, Richard Gabriel makes a strong case for the use of programming mediums instead of programming languages when either introducing programming to students or starting a new project.

He says:

“The difference between Lisp and Java, as Paul Graham has pointed out, is that Lisp is for working with computational ideas and expression, whereas Java is for expressing completed programs. As James [Gosling] says, Java requires you to pin down decisions early on. And once pinned down, the system which is the set of type declarations, the compiler, and the runtime system make it as hard as it can for you to change those assumptions, on the assumption that all such changes are mistakes you’re inadvertently making.

There are, of course, many situations when making change more difficult is the best thing to do: Once a program is perfected, for example, or when it is put into light-maintenance mode. But when we are exploring what to create given a trigger or other impetus—when we are in flow—we need to change things frequently, even while we want the system to be robust in the face of such changes. In fact, most design problems we face in creating software can be resolved only through experimentation with a partially running system. Engineering is and always has been fundamentally such an enterprise, no matter how much we would like it to be more like science than like art.”

[Highlights mine]

I too believe that learning and experimenting require a Language like Lisp, Scheme, Smalltalk, Python and Ruby which offer a read-eval-print-loop (i.e. an interactive shell). Naturally, you’ll always need the big-iron compilers but only when the program is perfected

As Frederick Brooks writes in The Mythical Man-Month, plan to throw one away, you will anyhow…. In most engineering fields, prototypes are routinely built using more malleable materials than the ones that are going to be used in production (for e.g. airplane prototypes made of wood). It’s only in our field, Programming, that people build prototypes using production-quality (but extremely rigid and constraining) languages like C++ and Java and spend so much time and money in this process that they are forced to ship the prototypes to customers with obvious consequences!

Using a malleable programming language

This semester, I am going to teach Programming Languages to second year university students. Those students have been exposed to C++ in the first year and Java at the beginning of the second year. Both programming languages are good for expressing perfected programs but are bad for experimenting.

(By coincidence, there were two interesting discussions on Slashdot (One Two.) following an article by some professors criticizing Java. Joel Spolsky thinks that it is perilous to use Java at school. I won’t even mention C++ as I personally think it’s the worst (by far) language to be used for teaching programming!

Together with Pascal Grosset who will be handling one of the lab sessions, I have been thinking a lot about what paradigms (and, hence, what programming languages) to use for my lecture. I think that I’ll only have time to introduce three paradigms and, hence, at most three programming languages (or mediums).

This is what we have come up with:

  • Functional programming with Scheme
  • Logic programming with Prolog (or, maybe, Kanren)
  • Scripting with Ruby

The first lecture

I did my first Programming Languages lecture last Friday and I enjoyed it a lot. I arrived in the lecture theatre at around 9:00 and I quickly installed OpenOffice.org on the Windows laptop there as I had prepared my presentation using OO Impress.

During the installation, I asked the 180 students how many of them found programming easy and only a few raised their hands (remember – those are second year students). I was a little surprised because I thought there were more. Anyway, I told them about my little theory that they should make a lot of effort now to acquire knowledge to be effective when they work so that they can return home early and enjoy life instead of having to stay overtime everyday :-)

I also told them that we were going to focus a lot on the functional, logic and scripting paradigms. And I also tried to make them understand that becoming a competent programmer require practice like all artistic endeavors. My first real lecture on Scheme will only begin next Friday as tomorrow is a public holiday.

Why Scheme?

I have been a fan of the Scheme programming language since I was introduced to it during my first year as a university student in France. Since then I’ve found out that Scheme is used at top universities like MIT and Berkeley to teach programming. Why is that so? Because Scheme is easy to learn yet, easy to use yet powerful!

I have decided to use the fantastic DrScheme IDE. It is multi-platform (Linux, Mac OS X and Windows) and is a joy to use. It’s, naturally, open source software. I am currently in the process of installing DrScheme in all the Computer Science labs.

I am still wondering what textbook I’ll use… I bought “How to Design Programs” by Matthias Felleisen, Robert Bruce Findler, Matthew Flatt, Shriram Krishnamurthi a year ago and it is an excellent book written by some of the makers of DrScheme. I am a little bit hesitant to use it as it uses slightly customized versions of Scheme instead of the standardized Scheme. Anyway, I’m still making my mind.

I have also ordered the Schemer triumvirate through Amazon and I expect to receive them in one or two weeks.

“The Little Schemer” is a little book (how surprising!) that covers functions (closures) and recursion. Many of you may feel that recursion is simple but Scheme guarantees that tail-recursive functions are executed without using increasing stack space hence the book goes into a lot of detail.

The second book, “The Seasoned Schemer”, talks about mutable state (i.e. variables) and about the special control flow constructs based on the continuations found in Scheme. Continuations allow for coroutines, concurrency, etc. and are important to understand if one really wants to be a Schemer (a Scheme programmer).

The final book is “The Reasoned Schemer” which is a book on reasoning (aha!). It introduces Kanren, a small library to transform Scheme into a better-than-Prolog programming language for logic and inference.

Why not Lisp?

I’ve also ordered “Practical Common Lisp” by Peter Siebel from Amazon. I have decided not to use Lisp because the de-facto IDE, Emacs + Slime, while extremely powerful, is too intimidating for young students. Another reason is that Common Lisp is a beast and is tough to learn…

Conclusion

Learning by experimenting is the best way to learn. Learning programming using Scheme is fun and rewarding as the language is so malleable. A University is not only a place where people go to get a degree. Rather it’s a place where intelligent people (students + academics) meet to share knowledge. Someone wrote on Slashdot:

“When Plato and Aristotle founded their schools, they didn’t put up a big sign that said “When you’re done, you get more money.” That wasn’t the promise. The promise was that by teaching you about the world, you would become a better person. That is to say, the founding concept of the University was that education lead to human excellence.”

My students will become better persons by experimenting with Scheme :-)

Creativity in Programming

I’ve just started teaching a new module today to second year Computer Science students. It’s the Programming Languages module where students are supposed to be exposed to alternative paradigms and programming languages.

Today I had a lab session with one of the group of students and, as lecture hasn’t started yet, I asked them to write a number of moderately challenging C++ programs for me to make sure they were competent programmers. Those students studied the imperative portions of C++ during Year I and object-oriented Java during the first semester of Year II so I expect them to be able to complete the lab sheet.

Just for fun, here are the problems I’ve asked them to solve. I’m sure most of you will find them relatively easy but, remember, the point is to make sure everyone starts with (more or less) the same grasp of imperative programming.

Problem 1 – Two kinds of Fibonacci

Write a program in C++ that prompts the user for any non-negative integer n and displays on screen the times required (in seconds) to calculate fib(n) both recursively and iteratively.

(I told the students about the C time() function)

Problem 2 – Generation of numbers

Consider the following algorithm to generate a sequence of numbers. Start with an integer n. If n is even, divide it by 2. If n is odd, multiply it by 3 and add 1. Repeat this process with the new value of n, terminating when n = 1. For example, the following sequence of numbers will be generated for n = 22:

22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

It is conjectured (but not yet proven) that this algorithm will terminate at n = 1 for every integer n. For an input n, the cycle-length of n is the number of numbers generated up to and including the 1. In the example above, the cycle length of 22 is 16.

Write a program in C++ that prompts the user for any positive integer n and displays on screen (i) the sequence of numbers generated for that n and (ii) the cycle length.

(This is a slightly modified version of a real ACM ICPC problem)

Problem 3 – String subsequence

Given two strings a and b, print the longest string x of letters which is a subsequence of both a and b. For example,

  • if a is pretty and b is typing, then x is ty,
  • if a is walking and b is king, then x is king and
  • if a is iris and b is aqua, then x is an empty string.

Write a program in C++ that prompts the user for the two strings a and b and displays on screen the appropriate x.

(I told the students about C++’s extensive string manipulation facilities)

Objective

My first objective is to make sure that students understand than programming can be fun and rewarding as an intellectual (unmarked) activity. My second objective is to make sure that the students are ready to digest whatever I’ve prepared for them as from Friday…

Factor? Scheme? Ruby? I’ll tell you on Friday :-)

The Story of Programming: great idea!

I came across a great blog entry “Books that should exist” by Daniel Ehrenberg, a well-known Factor hacker, today where he writes:

I, like many of you reading this blog, have an unhealthy interest in programming languages. Mine may be a little more unhealthy than yours. Whenever I hear the name of a programming language that I don’t know of, I immediately need to read about it, to get some basic knowledge of its history, syntax, semantics and innovations.

Most study of programming languages works by examining the properties of the languages themselves: how functional programming languages are different from imperative object-oriented languages and logic languages and the like. But what about a historical perspective? The history of programming languages is useful for the same reason other kinds of historical inquiry are useful. When we know about the past, we know more about the way things are in the present, and we can better tell what will happen in the future. The history of programming languages could tell us what makes things popular and what makes things ultimately useful.

Unfortunately, not much has been done on this. Knowledge of programming language history is passed on, unsourced, with as much verifiability as folk legend. The ACM has held three conferences called HOPL on this subject over the past 30 years, so all the source material is there. But apart from a book published in 1969, this is all I can find as far as a survey history of programming languages goes.

There is a limit to how much academic research papers can provide. The proceedings of the HOPL conferences aren’t bedtime reading, and they don’t provide much by way of a strong narrative. A new book could present the whole history of programming from the first writings about algorithms to modern scripting languages and functional programming languages so it’s both accessible to non-programmers and interesting to programmers. As far as I know, no one’s really tried. But it would be really fun to try.

I think this is a great idea!

I would love to read such a book. I would even love to contribute to such a book!

Factor, a practical stack language

I’ve just discovered Factor, a new programming language. It is a stack-based language like Forth and Postscript. Factor works on many different platforms.

I’m currently looking at it as one of the possible programming languages I’ll cover in my Programming Languages module at the University of Mauritius. Simple stack-based languages are interesting because they are low-level meaning that a student who understands Factor really understands how a computer works. And also the Java virtual machine which is also a stack-based bytecode interpreter.

Some example code

The Factor programming language is simple. For example,

10 20 30 + * .

displays 500. 10 20 and 30 are pushed onto the stack. + consumes the last two elements on that stack (20 and 30) and produces 50 which is pushed on the stack. * consumes the 50 and 10 and 500 is pushed. The . consumes one element of the stack (i.e. 500) and prints it on screen…

This morning, Pascal Grosset and I have been experimenting with different functions in Factor using the Factor workspace which is a great IDE. We have come up with the following:

: square ( x -- y ) dup * ;

This is a function called square that consumes one element of the stack (the x) and produces one element (the y). What it does is easy. dup duplicates the topmost element of the stack. * obviously multiplies the two topmost elements. That’s it.

: cube ( x -- y ) dup dup * * ;

Easy!

: big ( x -- y ) 10 > ;

big looks at the topmost element of the stack and replace it by t(rue) if it is bigger than 10 and (f)alse otherwise. t and f are Boolean values.

: negative ( x -- y ) 0 swap - ;

The swap is used to swap (what else?) the two topmost values on the stack. Notice that 0 is pushed before. And the – only does 0 – the number which was there already i.e. calculates the negative of that number.

: max ( x y -- z ) 2dup < [ swap drop ] [ drop ] if ;

What about this one? It contains a conditional statement (the if) which consumes three elements on the stack: a Boolean and two quotations (which are like Smalltalk and Ruby blocks which are evaluated later if needed). The first quotation [ swap drop ] will be evaluated if the condition is true and the second one [ drop ] otherwise. The 2dup function simply duplicates the two topmost elements on the stack. Get it?

Recursion in Factor

More complex Factor functions allow for recursion:

: fact ( x -- y ) dup 0 = [ drop 1 ] [ dup 1 - fact * ] if ;

Do you recognize our friend factorial? drop simply discards the topmost element of the stack. Notice that fact is called recursively until it hits the boundary case.

And finally,

: fib ( x -- y ) dup 1 <= [ drop 1 ] [ dup 1 - fib swap 2 - fib + ] if ;

This is another friend, the Fibonacci function. Have fun understanding it.

PS: Elie Chaftari says that according to Doug Coleman, one of Factor’s top gurus, you need to learn the following words (aka functions) by heart: dup, keep, 2dup, 2keep, swap, pick, rot, -rot, roll, -roll, 2apply, 2array, first2, nth, set-nth, append. Doug also advises to learn the following words for iterating: each, each-with, map, map-with, 2each, 2map.

Vikash Dhorasoo stops football

Two days ago, Vikash Dhorasoo announced that he was retiring from football.

He started playing at Le Havre AC, then spent a few years at Olympique Lyonnais (where he won two French championship medals) and even played for Milan AC (he was on the bench during that most dramatic Champions League final ever…). He was a member of the French national team and played during the 2006 World Cup.

Incidentally, he arrived at Lyon when Christina and I were studying there. We went to watch his first match ever for the club against Atletico Madrid and he was excellent. We even went to the same cinema once except that he was waiting in another queue and we did not have the courage to go and talk to him… Talking of cinema, Vikash Dhorasoo will also always be known as the football player who directed a film.

He played for the Mauritian team once during an exhibition match against Marseille and he was the best player by far.

He is without doubt the best footballer born of Mauritian parents ever. He played with Zinedine Zidane and Paolo Maldini against the likes of Steven Gerrard and Djibril Cissé. I wonder if we’ll ever have another as successful footballer as Vikash given the state of football in Mauritius…

I wish him good luck for the future.