Using Coconuts - a Pythonic Blog

Username:

Password:


Don't have an account? Get one!
What should I write on next?
Duct Tape (non-techie) 1
Black Friday Web Magic (non-techie) 1
Open Source Gaming: Part 2 1
Open Source Gaming: My Turn! 0
Polls

Watch Your Language

Warning: This entry is really long and almost definitely requires programming experience to understand.

So I told one of my friends that during my ride back to New York from DC I could probably get some sleep. She said she knows me better than that, and that I would most definitely not sleep the entire way. Turns out she's right, since I got a bee on my bonnet regarding language comparisons - "beginner" languages.

The two most popular beginner languages of today are Java and C++, each to its different class: Java is more common in high school compsci classes because of the AP Computer Science exam being Java-based, and C++ is more common in colleges because of... I don't even know why. Probably because of how powerful a language it is and the amount of doors it opens. Of course, then there are the few rebel teachers who see that...

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

... and...

#include <iostream>
int main(){
  cout << "Hello, world!" << endl;
}

... may be obfuscating the point of a simple helloworld program, and they prefer Python's

print("Hello, world!")

These teachers' numbers are growing, especially since colleges are begining to adopt Python as their Programming 101 language simply because of the lesser amount of syntax needed, allowing the course to focus on programming concepts instead of whether to use a double quote or a single quote for a string.

Okay, maybe I'm not qualified to talk about what these languages are like for a beginner, since none of them were my beginning language. Pascal was.

program helloworld;
begin
  writeln("Hello, world!");
end.

But especially because none of them was my starting language, perhaps I can be impartial, right? Or maybe try to? A little? Okay, I'll just talk about what they were like for me then.

Java was the first of these three that I learned. I encountered it in the Accelerated Computer Science course at my high school, in the context of the JKarel robots. Oh, those were the days.

http://blog.opensourcenerd.com/upload/hello-karel

Hello, Karel! source

I do have to commend Karel for being a really friendly little bugger to explain to me what the heck object-oriented programming is. Believe it or not, it was a fairly large paradigm shift going from the Pascal/BASIC/C mentality of primitive types only, organized in structs or my own weird data structures via arrays into a "class" which magically contained its own data and had its own methods and other properties.

If it wasn't for Karel, though, Java would have just been a really inconvenient way for me to write procedural programs: having to wrap everything in a public class foo to make it go. I'm afraid this may have happened had I learned C++ instead, since it doesn't have a nice little Karel library (that I know of). I might just have stuck to the procedural way of doing stuff, only coding classes just because the teacher wanted me to, or some other stuff like that.

http://blog.opensourcenerd.com/upload/confused-student-cat

Can haz getCheesburger() metud?

Python has a Karel-ish tool as well, called Guido van Robot. I am not as familiar with it as opposed to Karel, because I just picked up Python as I went, but GvR was supposedly fun to code the backend for (or so I hear)?

Oh, Python. You restored my faith in programming needing a human brain to not be a syntax checker and on some things making sense. I won't go into great depth, but take a look at some of this nonesnse I ran into in my Java course:

public class foo{
  public static void main(String[] args){
    String a = "foo";
    String b = "foo";
    a += "bar";
    b += "bar";
    System.out.println(a + "==" + b + " ==> " + (a==b));
    System.out.println(a + " equals " + b + " ==> " + (a.equals(b)));
   }
}

The output:

foobar==foobar ==> false
foobar equals foobar ==> true

What?! To someone who does not know what a memory address is, this makes very little sense. Plus, isn't Java supposed to be object-oriented? If you're comparing the equality of two objects, perhaps it shouldn't compare their references, but their values. And, while always using methods is a nice way to be organized, why do I need a special method for comparison? There are builtin operators for that. If I wanted to compare memory addresses, I'd use pointers. Or, not Java. Python got it right:

a = 'foo'
b = 'foo'
a += 'bar'
b += 'bar'
print(a + "==" + b + " ==> " + str(a==b))
print(a + " is " + b + " ==> " + str(a is b))

The output:

foobar==foobar ==> True
foobar is foobar ==> False

C++ got it right, too, and in a less ambiguous way than Python. == compares memory addresses unless it's overloaded by the writer of the class to do something else. While this allows it to keep the low-level-ness of C, it also allows programmers to customize their classes to, well, act like objects are supposed to act.

http://blog.opensourcenerd.com/upload/tell-me-when-its-over

I warned you, didn't I?

What am I saying? Java may be fine for a little while, but it gets unintuitive fast. Really fast. Say you wanted a mutable-size array. In Java? import java.util.ArrayList. In C++? #include <vector>. In Python? There by default. That's fine, but how do you use these? In each of the cases below, a is one of these arrays.

// Java
a.get(pos);              // getting an element
a.set(pos, some_object); // setting an element
a.add(some_object);      // adding an element to the end
a.add(pos, some_object); // adding an element at position pos
a.addAll(b);             // adding all elements of another array
a.size();                // how many elements are there?
// C++
a[pos];                    // getting an element
a[pos] = some_object;      // setting an element
a.pushBack(some_object);   // adding an element to the end
a.insert(a.begin()+pos, some_object);  // adding an element at position pos
a.insert(a.end(), b.begin(), b.end()); // adding all elements of another array
a.size();                  // how many elements are there?
# Python
a[pos]                     # getting an element
a[pos] = some_object       # setting an element
a.append(some_object);     # adding an element to the end
a.insert(pos, some_object) # adding an element at position pos
a += b                     # adding all elements of another array
len(a)                     # how many elements are there?

Java is all methods, C++ is long-winded and weird with its iterators, and Python is short and sweet. But, honestly: a.get(pos)? And, while C++'s versions of the add and addAll commands may be rather opaque to those who don't know iterators, iterators are much more powerful than anything Java has. Let's try to sort that array we got, something many beginner programmers may want to do.

// Java
Object[] ca = a.toArray(); // XXX: errors/warnings!
Arrays.sort(ca);
for (int i=0; i<a.size(); i++)
  ca.set(i, ca[i]);
// C++
#include <algorithm>
// ...
sort(a.begin(), a.end());
# Python
a.sort()

Java is obscene. In this example, Python may seem to have the upper hand, but it really doesn't: the sort() method is builtin to the list class, and if I were to, for example, make a LinkedList class, or something else that's not a simple flat list, I'd be hard pressed sorting it without something like C++'s iterators. For a beginner, though? C++ can make just as much sense as Python with a little explanation.

Okay, so I don't like Java. So what? Well, I'm trying to maybe get the word out that it is not all that good of a beginner language! Many students only take an intro CS course, and if they learn Java, they really aren't left with something usable later. C++ either, because both Java and C++ take extra effort to get a project or script off the ground. Python is instant-gratification, though, and even a biologist might find it useful to write a small script to process a large data file or the likes.

And, for those who go on to bigger and better compsci things, both C++ and Python offer large libraries and sets of cool tools for everything from OpenGL to web development to GUIs to XML parsing, etc. Not that Java doesn't but it's at the midway between "harder, but efficient and powerful language" and "sluggish, but easy and tool-packed language", stuck somewhere at "rowing a boat in a lake of runny molasses".

http://blog.opensourcenerd.com/upload/failboat

The bottom line, though, is that in the selection of beginner languages you can do much better than Java. I personally like the way classes here at NYU-Poly are structured: CS 111 is Python, CS 112 is C++, then advanced courses follow.

You can do much worse than Java, too. I feel bad for the poor student somewhere whose first language was Lisp. Or Brainfuck.

Sorin says... source permalink

Actually python is very object oriented and very convenient.

a == b

is actually just a compiler trick that get's rewritten to

a.__eq__(b)

You can override the __eq__ and get weird stuff like C++

on 2009-09-30 14:09:23.022674

if lisp was your first language, you'd be a straange little child

on 2009-09-30 16:22:24.096660

I was about to say C++ allows more operator overloading, but then I looked it up and it appears Python allows just as much.

Still, Python is much slower than compiled C++. I wish it weren't because it's just so much prettier!

on 2009-09-30 19:12:52.824556
McScope says... source permalink

I'm not familiar with C++ iterators, but java does have an iterator class. In my experience they have been clunky, ridiculous beasts.

I think it might be worth looking into changing the way programming classes are taught. I had the same experience as you, it took me a long time to realize that object orientation was something more than just "public main{" window-dressing on my code. Perhaps we should start teaching with a language with only primitives, then pose them harder and harder problems till they start constructing their own data structures. At that point, give them object oriented code and let them see how useful it is for solving exactly the problem it was created to solve.

on 2009-09-30 20:54:52.803828
McScope says... source permalink

Try this for the java arraylist sorting.

import java.util.Collections;

Collections.sort(colours);

Seems much shorter, not intuitive like in python, but oh well. I think the objects have to be comparable for this to work, but not sure (haven't looked at API)

on 2009-09-30 21:00:34.892642
nstarr says... source permalink

Fun fact - MIT's intro CS course was taught in Scheme (a Lisp dialect) until something like a year or two ago when it switched to python. God only knows how that worked out, I know it took me a year or two of normal languages before I cam close to understanding lisp. I'm glad I did, though, it (or any functional language) is great to learn, really opens your eyes. I much recommed it if you've never tried.

on 2009-09-30 22:10:46.188663
bvargo says... source permalink

My first real language was z80 assembly (some basic and logo came before that). If that was taught before higher-level languages (C/C++ included), then everyone would better understand what is going on in basically any language. Of course, if assembly was taught during an introduction course, then there would not be many people interested in the courses. This also brings up the question about what the CS class should be about. I would like to think that CS is about algorithms and math, not about petty things such as the language used. Running code, or the code at all for that matter, is more a computer engineering topic in my humble opinion.

Anyhow, I also wanted to say that the following

a = "foo";

b = "foo";

a == b;

in JAVA can actually (and usually does) return true, depending on your JVM version and runtime conditions. The Sun JVM will internally combine identical strings in order to save memory, only differentiating between them until one is modified. However, because you add "bar" to each string in your example before printing, the two strings are separated internally, as the original string has been modified. Even though the two strings are still the same after both instructions execute, the JVM will not merge the strings again. Thus, a==b returns false in your example. However, if you had initialized both strings to "foobar" and done nothing else, a==b would probably return true. The latter would have used less memory as well. Isn't JAVA great?

on 2009-09-30 22:40:23.668316
bvargo says... source permalink

Of course I mean modified in the English sense of the word. JAVA actually makes a new string, since a String object is immutable. Thus the "separating" is actually JAVA making a new String object, on which it does not optimize for space.

on 2009-09-30 22:55:24.461072
Hello, world! says... source permalink

++++++++++>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.

on 2009-09-30 23:04:25.703972
pcardune says... source permalink

Don't forget about the version of Guido van Robot that's implemented in Javascript and runs in your browser (http://gvr.carduner.net firefox only).

The fun part about writing the backend was that with python you could just use getattr to dynamically link language tokens to the internal python API. Add a new method to the python API and it is instantly exposed as a keyword in the language. You can do this with Java's introspection library but I don't think it is quite as trivial as in python. I have no idea how you would accomplish this in C++.

Don't forget that in python you can sort anything that is iterable via:

>>> sorted(iterable)

That takes the cake from C++, even with a custom linked list object (or anything else) as you don't need to import anything special.

Java purposefully stayed away from any and all operator overloading including string equality in part to keep people from misusing operator overloads. The craziest operator overload I've seen in python code that I've actually used was for building file system paths. You could say:

>>> directory = path("foo")/"bar"/"baz"

or:

>>> foo = path("foo")
>>> bar = path("bar")
>>> directory = foo/bar/"baz"

and you would end up with a file system path using the correct separators. This sort of operator overloading is manageable within the context it was made for - writing little shell script like programs - but under no circumstances would you ever want to use it along side any math related code. For example:

>>> mb = 1024
>>> sorted([(len(open(foo/bar/fn).read())/mb,fn) for fn in (foo/bar).listdir()])

which would give you the list of files in the "foo/bar/" with their sizes in megabytes in ascending order. Get's confusing when you start dividing by numbers again on the same line of code. Not to mention the confusion that

>>> "foo"/bar/"baz"

will raise an exception.

on 2009-10-01 07:22:21.548688
jboning says... source permalink

Whoa, giant comment thread!

I've got to say, I don't think learning Lisp as a first language would be all that bad. It's easy to joke about parentheses, but I think that when done correctly, a course using Lisp could do an excellent job of teaching programming concepts and paradigms in a way that they can be easily brought to other languages.

on 2009-10-01 22:06:34.860832
New Comment
You're not logged in! Log in to be awesome!
Format: BBCode ReStructured Text

Author (max. 20 characters):