some thoughts about immutable programming
ajoo 2002-05-07 07:23:21 Today, when I was reading C++ View, I saw an interesting example.
Description:
we have a list in memory that holds all the friends we have. We'll also need to add it to database.
Suppose we have a method
void addFriend(Person p)
{
friends.add(p);
addToDb(p);//if exception's thrown out, we need to undo in friends!
}
The problem exists when either friends.add() or addToDb() throws exception. then we have to undo the changes we've made to db and to the list.
According to the author, "try-catch" can work, but it'll become very tedious and hard to maintain when the number of statements requiring "try-catch" scales up. So a transaction object should be used here.
Here, although transaction object can work, but it still requires us to write an undo operation for each one, and sometimes it's not trivial to write an undo method.
So what do I suggest?
Although db operation cannot be immutable, in-memory operation certainly can! If we do immutable programming, we don't need to undo at all!
don't believe?
Suppose the friends list is an immutable structure, i.e.
List
List cons(Person);
where list.cons(p) only returns a new list instance without touching the old instance. (curious how this can be implemented by constant-time and linear storage? I'll give it later)
ok, if that's true, what can we do to the addFriend method?
void addFriend(Person p)
{
List tmp = friends.cons(p);
addToDb(p);
friends = tmp;
}
Ha ha, does that solve the undo easily?
Here is an immutable list impl
public interface List
{
public List cons(Object obj);
public Object getFirst()throws java.util.NoSuchElementException;
public List getTail();
public boolean isEmpty();
private static final EmptyList singleton = new EmptyList();
public static List instance(){return singleton;}
}
class ConsList
{
public List cons(Object obj){return new ConsList(obj, this);}
public Object getFirst(){return hd;}
public List getTail(){return tl;}
public boolean isEmpty(){return false;}
private final Object hd;
private final List tl;
ConsList(Object hd, List tl){this.hd = hd; this.tl = tl;}
}
class EmptyList
{
public List cons(Object obj){return new ConsList(obj, this);}
public Object getFirst(){throw new java.util.NoSuchElementException();}
public List getTail(){throw new java.util.NoSuchElementException();}
public boolean isEmpty(){return true;}
EmptyList(){}
}