December 9, 2005

Teaching Mathematica as First Programming Language…

Posted in Computers, Education, Lisp, Mathematics, Programming, Scheme, Uncategorized at 1:57 pm by pmatos

is worse than shooting yourself in the foot… worse than shooting yourself in the head… is like shooting a whole bunch of students in the head, his friends, parents and colleagues. I would better call it a genocide.
From the wikipedia definition of genocide:

Genocide is (…) Killing members of the group; Causing serious bodily or mental harm to members of the group; Deliberately inflicting on the group conditions of life calculated to bring about its physical destruction in whole or in part; Imposing measures intended to prevent births within the group; and forcibly transferring children of the group to another group (…)

Students learning Mathematica as a first programming language are most probably mentally mutilated beyond hope of regeneration. In what follows I will explain why this is so.

During my degree in Software and Computer Engineering I had the possibility to learn programming in various languages like C, C++, JAVA, and some more eccentric languages like Scheme, Common Lisp and Mathematica. During the last years teaching Programming Fundamentals in Scheme as a first Programming Language in Software and Computer Engineering and following students from the Mathematics Department which learn Mathematica as a first Programming Language I’ve noticed the following differences:

  • Mathematica does not ease teaching students Programming Techniques, while Scheme does.
  • Mathematica makes it hard to teach good programming styles while the PLT Scheme approach makes it much easier.
  • Mathematica makes the learning of abstract datatypes (ADTs) extremelly difficult, while Scheme mostly enforces it.
  • Mathematica makes it even more awkard the teaching of orders of growth while Scheme does not.
  • Usual Programming Concepts like Interpreter, Compiler, REPL are not easily taught to students using Mathematics. PLT Scheme makes them explicit.

Now, I’ll try to detail each of the previous items in more detail.

Programming Styles

A beginning programmer needs, more than usual, that tools work on his side. No need for highly extensible, general-purpose, do-all tool (that’s why in general everyone works in windows, and why no beginner starts programming in emacs). If they are learning a programming language they already have a steep curve to go through, no need for another one to learn about an editor or how pretty-print stuff, indent or anything else.

Mathematica interface goes against these principles. Its interface is highly problematic, counter-intuitive and ugly. No help source colouring is provided and paren-matching functions are as simple as they can be. Check the snapshot!

  • It’s hard to keep track of what each parentheses close;
  • No colouring at all;
  • No support for indentation – the code is indented automatticly but if you for some reason miss the indentation and destroy the automatic indentation (remember, they are only beginners) it’s hard to get it back in place;
  • Copy-pasting the code can get a harsh job due to newline problems, etc… (I was never able to understand these issues)

Now, for your delight, check for example a PLT Scheme snapshot.

ADTs

One thing which is particularly annoying in Mathematica is its uses of lists. Students learning Mathematica know surely all of the following functions for lists: PreppendTo, Preppend, Append, AppendTo, Length, First, Rest and [[_]].

Lists are a very good datatype but one that should be used with care not to shoot yourself in the foot. The major problem is Lists in Mathematica are not Lists. Lists in Mathematica are vectors, uni-dimensional tensors, and what makes things more irritating is that they are called lists. Check the following copy-pasted from Mathematica 5.1 help on List:

- {e1, e2, ...} is a list of elements.
(...)
- {a, b, c} represents a vector.
- {{a, b}, {c, d}} represents a matrix.
- Nested lists can be used to represent tensors.

Geeez, check the first line, oh it’s a list of elements… some lines below… it’s a vector… 2 lines below, oh no, nested lists…

This will not make sense of any student and imagine what a beginning student will learn from this? Lists and vectors are probably the same. Which is utterly incorrect!

From the Dictionary of Algorithms and Data Structures on list:

Definition: A collection of items accessible one after another beginning at the head and ending at the tail.

And on vector (also known as 1D-array):

Definition: A set of items which are randomly accessible by numeric index.

So, definitely this is a vector. How we really know the Mathematica list is a vector and not a list? Check next section on orders of growth.

This seems like a stupid non-sense that any student may go through without any problem but it is not true. Mathematica students learn talk about lists and which is ultimately worse, “think” about lists when they really mean vectors. And these are basic ADTs, every other ADT knowledge will come distorted because of this.

One can think:

Oh, no big deal, I can explain my students that lists and vectors are one. There are list functions and vector functions that work exactly on the same datatype (which is true).

You can explain this fact and probably 40% (at best) of them will understand but this will not help. When they get to learn other programming languages like C++ (which have separate STL List and Vector), Common Lisp, Scheme, etc, etc, etc… they won’t understand.
Using Mathematica and getting used to the fact that lists and vectors are the same will make them bad programmers for the rest of their days and will mutilate them and everyone who this person might teach.

Orders of Growth

Although we do not teach our students much about orders of growth in a first programming languages course, we do mention about the computational cost of some function and the computational cost of each ADT we use. However, we do know most students in their first project are eager to make them as computationally efficient as possible so that it’ll run faster than of most of their colleagues, not knowing that:

Premature Optimization is the Root of all Evil!
— Donald E. Knuth

Imagine that a student A is asked to define a function in Scheme that given an ordered list of numbers and a number (which is known to be in the list) should return the position (1-based) of the element in the list. A smart student will try to make is run as fast as hell so it uses a neat trick:

  ;; Returns the position of a given element in an ordered list.
  ;; (give-element '(2 3 6 8 15) 8) => 4
  (define (give-element-fast l n)
    (define (aux l i)
      (let* ((len (length l))
             (mid-pos (inexact->exact (ceiling (/ len 2))))
             (n-element (nth l mid-pos)))
        (cond (( n-element n)
               (aux (take l mid-pos) i))
              (else 
               i))))
    (aux l 1))

(defined nth and take for Scheme, almost as defined in Mathematica to resemble [[_]] and Take, which for Schemers is Take is take when receives a positive argument and drop when receives a negative argument. Code is in the end of this blog post.)

This is a usual recursive function with no-side effects that will as fast as possible try to compute the position given the fact that the list is ordered. A simple-minded student B will do in Scheme:

  ;; Returns the position of a given element in an ordered list.
  ;; (give-element '(2 3 6 8 15) 8) => 4
(define (give-element-slow l n)
    (let loop ((l l) (i 1))
      (if (= (first l) n)
          i
          (loop (rest l) (+ i 1)))))

Let’s make the same students define these in Mathematica. So student A:

GiveElementFast = Function[{l, n},
      Module[{lst, i, len, midpos, nelement},
        lst = l;
        i = 0;
        len = Length[lst];
        midpos = 1;
        nelement = Infinity;
        While[nelement != n,
          len = Length[lst];
          midpos = Ceiling[len/2];
          nelement = lst[[midpos]];
          If[nelement 
Let's take a bunch of benchmarks now.</del>(In fact I did take some benchmarks but unfortunately, posting them along the post would take more time than it should and the results are intuitive.)
What happens is that the time to search a list in Scheme with the Fast Procedure is much larger than the Slow one, and in Mathematica happens exactly the opposite. This is exactly due to the fact that Mathematica Lists are vectors and the Fast Procedure is only really fast if the datatype is a vector since getting an element from a list is O(n) and getting an element from a vector is O(1) (which means that getting an element from a list is done in linear time with the size of the list, and constant in the size of the vector). So, in fact, the approach student B took when developing the functions was the correct one since he probably new the orders of growth in list access, what he didn't knew and that's why his approach fails in Mathematica is that Mathematica cheats you when talking about lists. Student A approach although wise with vectors is naive with lists and or he knows he is working with vectors in Mathematica (which is rarely the case if we are talking Mathematica as a first programming language) or he gets is fast just by luck. Either case, something is wrong and potencially confuses the student. Mathematica is great for symbolic manipulation, data plotting and programming of rather simple software prototypes but extremelly bad to teach programming concepts. Seems simple and straightforward to those programming in Mathematica for a long time but cannot see the damage they are inflicting to their students.

<strong>License</strong>

And of course, there are the license issues. Mathematica is cross-platform but also is PLT-Scheme and many others. However, if you find a bug in Mathematica 5.1 (for example, the extremelly annoying bug of numlock not working ok on Linux Systems) you have to wait for the next release (probably a couple of months), if you find a bug in an open source free system you contact the developers and probably in less than a day they put online a binary version of the software working as you wanted to.

<strong>Last Comments</strong>

Surely Mathematica is not useless. Mathematica is a powerful symbolic manipulator with a nice embedded Programming Language, still using it for a course on Programming as a first Programming Language should be considered a criminal offense, and those enforcing its use should revise the course or accept the death penalty.

<strong>Other Code</strong>
Nth:

(define (nth l n)
    (if (= n 1)
        (first l)
        (nth (rest l) (- n 1))))

Take:

(define (take l n)
    (define (take-aux l n)
      (if (= n 0)
          ()
          (cons (first l)
                (take-aux (rest l) (- n 1)))))
    (define (drop l n)
      (if (= n 0)
          l
          (drop (rest l) (- n 1))))
    (if (> n 0)
        (take-aux l n)
        (drop l (- n))))

3 Comments »

  1. Mário Lopes said,

    I’m delighted to see someone teaching and having its own blog where one shares his experiences. This is very interesting and other people, namely teachers, should follow the example.

    Regarding the article, Scheme was also the first language I’ve learnt during the degree of Computer Science at FEUP, although I already had experience with other languages, like PHP, ASP, C, etc…

    Now that I’m almost finishing my degree and that I have had experience with several other languages (Python, Java, Ruby, Prolog, etc..) I most definitely recommend Python as the first programming language for these kind of students (Computer Science). It can be procedural and object oriented at the same time, so you can avoid one thing while teaching the other. It forces students to make cleaner code and it’s very easy to learn. It has a lot of libraries to do almost everything they want.

    Unfortunately, Python doesn’t seem very popular among teachers. Is it because USA embraced Scheme and Portugal has to copy them?

    Since I learned Scheme, I’ve never touched it again. And neither my colleagues I asure you. So, overall, and if you allow me to disagree, I don’t consider Scheme a good language to start with too (same as Mathematica). Scheme has Lots of Incredible Stupid Parenthesis, doing list manipulation is tedious, lambda ain’t good and libraries are quite limited. Plus, performance has a lot of improve. As I said before, Python would be a better bet.

  2. pmatos said,

    Thanks for your comment, it’s always nice to share ideas.
    Before starting my comment to your comment let me tell you my oppinion is surely biased due to the fact that I use Scheme on a daily basis for serious professional programming and I have not used Python much since I learned it.

    Since you’ve only learned Scheme as a first programming language without touching it ever again I understand your oppinion, mainly if you have already seen scheme more than a years ago.

    I don’t think Portugal HAS to copy the USA but there is no doubt US, mainly MIT students are able to outsmart our students so following a good example (the MIT example) is not to ‘copy’ the US but to follow the best example there is since MIT is regarded as one of the best engineering schools worldwide.

    I do not wish to confront Scheme and Python as languages since it was also not my intention to tell that Scheme is best than Mathematica or vice-versa but what would be best to teach as a first programming language and I still think that it is Scheme. Scheme is simple, enabling students to learn a few commands to do a lot of stuff, programming paradigms are explicitly enabled for students to learn. They can easily learn concepts like Recursion, Processes (recursive and iterative), Imperative Programming, Functional Programming, Higher Order, etc. The PLT Scheme IDE is perfectly suited to teach programming to a new students, there are not many functions so students will not get lost but do enable them to take as much as scheme as they can. Another nice feature is that we can easily restrict the language in DrScheme by the use of teaching packages and generate interfaces for their projects providing a black-box so they concentrate only on what they need to learn.

    Still, considering the features you mentioned about Python. Scheme also has Object Oriented Constructs. Java Like classes and Common Lisp Like classes (CLOS-like). You can program under emacs which makes programming in scheme more powerful if you don’t like the simple interface provided by PLT Scheme. Parentheses are one of the nicest features of scheme. And they are surely not stupid. They are one of reasons why LISP is so powerful and makes code and data seemlessly one object only. Questioning why there are parenthesis between scheme expressions is like questioning about whitespaces between words in a newspaper.
    Lisp Manipulation is incredibly easy and straightforward, but still if you don’t like you have a LOT of other data structures available. SRFIs (srfi.schemers.org enable you to have a lot of functions and datastructures handily available). Lambda is extremely powerful and useful and performance in compiled scheme code may be compared to C++. If you wish some benchmarks or if you would like to expand this explanation in any direction drop me a note.

  3. Schemer said,

    I know most students probably don’t like Scheme much, but it’s a fun language to program in (in fact I far prefer it to python).

    Implementations like Chicken have compilers, object systems, (although we schemers are happier with functional programming) and have libraries for doing “fun” stuff (eg. games, graphics, etc).

    The parenthesis thing is subjective, but scheme has several technical advantages to python:

    1) recursion isn’t horribly limited as it is in python (to implement functions like filter and map efficiently you have to write them in terms of folds that use assignment)
    2) scheme has macros so you can add cool syntactic constucts (in fact this page http://www.cs.toronto.edu/~gfb/scheme/iteration.html adds for loops to scheme with three macros, add some incrementing opersators for synactic sugar) — not only that but the default macros are hygeinic, so they are really safe, and procedural macros are also offered in most implementations
    3) scheme has continuations

    Now, some of these things seem redundant if you’re programming in python, since it already has a nice syntax, but I wouldn’t write off scheme unless you’re sure you only want to do object oriented programming.

    By the way, in my (US) university they only taught us C++ (though the freshmen are learning python), not scheme. So maybe that would explain why I’m a fan and you loathe the language.

    Last, scheme is much more than just an academic’s language. I’m not a TA, professor, or academic by the way. Just want to share the fun of scheme!


Leave a comment