Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: immutable BigInteger



I am not debating that immutable objects makes concurrent programming easier - it is just that immutable objects do not model real world (domain) objects very well.

If I have an instance of the car, and I paint it RED, I don't get a new instance of the Car,

so

Car newCar = car.paint(RED)

is not good.

I want

car.paint(RED)
car.getColor() == RED

If I have two users that each want to paint the car a different color, you have a conflict and some sort of synchronization and ordering is required.

so it would be

sync(car) {
if(car.getColor()==BLACK)
   car.paint(RED);
else
   error you can't paint a non-black car
}



Immutable objects only seem to work well for objects with very few properties.

A lot of concurrent programming deals with complex domain objects, and thus external synchronization is required (in most cases).


On Oct 16, 2007, at 4:32 PM, Charles Miller wrote:

1) As a general design rule, objects that represent values should be immutable.

There are a lot of practical advantages to having immutable value objects: you can use them safely in sets and as keys in maps, you can pool and flyweight them, and yes, they're much safer in a multi- threaded environment. But these are side-effects of the fact that making something immutable makes it an order of magnitude simpler, conceptually.

The number 6 should always be the number 6. The string "blah" should always be the string "blah". It doesn't make sense to redefine the number 6 to have a value of 7. Values are concrete, and that concreteness gives you the confidence that 6 + 7 will _always_ give you the same result, whenever you happen to calculate it.

(A friend of mine once told me of a project, I can't remember in which language, where somebody accidentally redefined the empty string. Hilarity ensued.)

2) Immutable objects are _safer_ than "thread-safe" objects

When an object says it is thread safe (StringBuffer, for example, or the pre-1.2 collection classes), all it means is that the _internal state of the object will remain consistent_ if the object is used across multiple threads. It doesn't mean that the object itself can be used across threads safely. For example, the following (admittedly artificial) code:

public static BigInteger triple(BigInteger int)
{
   return int.add(int).add(int);
}

This method is only reliable because BigInteger is immutable. Even if you were to synchronize every single method on your mutable BigInteger class, you would not be protecting it from having its value changed halfway through the operation, leaving you with a value that isn't three times anything, let alone the number you passed in.

The safety that is generally promised by "thread safe" objects is such a weak kind of safety that it is largely being abandoned as a feature of the Java standard libraries. For the very rare case where internal consistency across threads may be all that is required, wrappers like Collections.synchronizedFoo() are provided.

It's really no accident that functional languages like Erlang, where everything is an immutable value, are being touted as the safe solution to multi-threaded programming. Safe multi-threaded programming is HARD, and the more code you write that is provably safe, the fewer times you're going to be up at 3am cursing at your debugger.

There are a lot of really interesting papers out there about how mechanisms like Java synchronization are simply the wrong way to deal with the inherently non-deterministic nature of concurrent applications, and inevitably lead to disaster, ruination and death.

3) Immutable objects are less efficient than mutable ones... but most of the time you don't care.

Object allocation in Java is distressingly cheap. Garbage- collection of young generation objects is reasonably inexpensive. The Java language is _designed_ with the creation and destruction of lots of little objects in mind, and it does it very well. As such, it makes sense to err on the side of creating too many objects.

There are, of course, exceptions. That's why we profile code. For the most common case where immutability can be a problem -- building strings -- Java offers a mutable StringBuilder. This is a pretty common pattern: offer a builder class to construct objects piecemeal, then have the immutable value pop out of the other end.

You've found a case where the immutable bignum classes in Java aren't efficient enough for you, and the only alternative you have is to abandon them and mess with arrays. The problem here isn't that BigInteger and BigDecimal are immutable, having them be immutable is the Right Thing To Do. The real problem is that providing a high-performance library for arbitrary precision arithmetic would _also_ be the Right Thing To Do, but Java doesn't.

I'm sure some exist, though. Have you tried Googling?

C

_______________________________________________ Do not post admin requests to the list. They will be ignored. Java-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/java-dev/email@hidden

This email sent to email@hidden
References: 
 >Re: immutable BigInteger (From: robert engels <email@hidden>)
 >Re: immutable BigInteger (From: Charles Miller <email@hidden>)



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.