Tuesday, February 13, 2007

IROS 2006 on IEEE Xplore

I have just noticed that papers from IROS 2006 are now on IEEE Xplore. My first paper is here.

Sunday, February 04, 2007

Programming - Parameter Passing

The reason I'm talking about this is because right now I have to program quite a lot, and many friends of mine have just started to learn how to program.

It's quite weird when I think back to the time I was little, I was so thrilled to practise programming but I made almost practically nothing. In the past few years, I don't have that much passion, but I have made some successful programs, and I'm still doing it.

Still, programming itself is interesting. Especially when no programming language presents 100% consistent design. You can see a lot of language designers struggle to make sense out of something that did not make sense. The proof that you cannot make a 100% consistent (high-level) programming language is simple — it's because variable types that the machine can represent are limited to integers and floating point numbers. Maybe if you have a different machine, you can make a more consistent programming language. The important thing is that in order to write an efficient program, you might need to delve into abundant details of your computer architecture and how your compilers work.

Quite a long, boring, and irrelevant prologue? Let's start the subject now :P

A bit of warning: This is not for a very beginner who does not know what pass-by-value and pass-by-reference are.

Pass-by-Reference

This is the thing that new programmers must be aware of. In C, it is made clear that all parameters are passed by values. This is quite a consistent design, but it makes your code a little bit harder to read when you want to change something "outside". You need to pass the "reference" (equivalently called "pointer") to the function, and the function will change to value pointed to by that reference.

C++ introduces a new way to pass parameters, which when compiled, gives the same code as the old-fashioned pointer passing. The bad thing is that people can write their code using either the C-style pointer passing or C++ pass-by-reference type (&), compelling programmers to look at the manual more often.

Pascal and Delphi already have this parameter-passing scheme since their very first design. "var" keyword works exactly the same as C++ "&" operator. It makes new programmers learn the difference since the beginning, and they do not have to know anything about pointers. However, pointers are still needed, and by the time they learn about pointers, they will discover that they can write their code either way.

In Java, this issue is quite crucial but beginners do not seem to know the difference, and they actually make a lot of mistakes from not understanding parameter passing.

Java: All parameters are passed by reference except primitive-type parameters.

This means if you want to change your parameter inside without affecting the object passed from outside, you should "clone" it before.

On the other hand, some high-level languages offer a weird scheme:

MatLab: All parameters are passed by value.

In fact, this is not always true, but it is what usually happens. MatLab is smart enough not to copy the object if you do not modify it in the function. People who do not know about this usually change entries of a big matrix passed as an input parameter, forcing MatLab to copy this big matrix. Therefore, the good practice is to copy the small part you want to modify to a new matrix, then modify the new matrix instead. (If you need to change the whole matrix, you have no choice.)

Passing the Clone = Pass by Value

If you want a pass-by-value parameter whose type is an object, some compilers will copy the object for you, but some compilers might not allow you to do so. C will copy the object for you, but it might not give you the result you want because the way it copies your object is too simple. It copies every bit from your original object (which should be a struct) to the local parameter. What might go wrong with this is when your object contains some references to other objects, and you want the copied object to create new references of its own. What you are supposed to do is to "clone" the object first, then pass the clone's reference to the function.

This is the same as in Java, since you cannot pass an object by its value. It is safe to clone the object first if you are not sure if the function will change your object when you don't want it to. However, some functions might clone the input parameter inside again to avoid changing the passed object, so one excessive clone operation will be made. This could happen while interfacing classes written with different disciplines. To resolve this, code writers should provide sufficient documentations regarding this issue.

C++ allows you to overload the "copy" operation when an object is passed by value, which is the same thing as "clone". This does not cause any extra running time. All you need to do is to implement a new "copy" constructor.

Details in C++: The copy constructor of type T is T::T(const T&). It will be invoked both when the object is passed by value and when a new object is initialized using "T NewVar = ObjectOfTheSameType;". In fact, any initialization "T NewVar = Param;" will be converted into "T NewVar(Param);" and the constructor with one parameter of the same type as "Param" will be called.

However, if the pass-by-value parameter is not modified inside the function, it is more efficient to pass that parameter by reference instead because the object will not be copied. You can specify this type of parameter by adding "const" keyword.

Example:

The following two functions give the same result (T can be any types with copy constructor, including primitive types):

void f(T x)
{ ... }

void f(const T &rx)
{ T x = rx; ... }

So, if you do not need to modify x inside f, it is more efficient to write

void f(const T &x)
{ ... }