Scala's lists are immutable, yes. But they aren't thread-safe.
That's because internally scala lists *ARE* mutable. In an attempt to
work around JVM limitations and make scala fast, scala lists are
actually mutable for a while as long as nobody reads them, in order to
make repeated adds fast. So, this:
[a :: b :: c :: d :: e :: Nil]
in scala does NOT in fact create 4 lists. It creates just one and
makes a bunch of add calls.
Unfortunately, even Odersky's out of this world genius is fallible.
Specifically, there are conditions where a shared immutable list in
scala cause multi threading bugs. you know the type - impossible to
debug, tend to never show up when a debugger is running, race
conditions, bugs that are only reproducible on 2-core or even 4-core
systems, and in general pains that can take you years to solve.
Long story short: Scala is not a panacea. In fact, in this particular
aspect, Scala sucks.
Silver lining in this thundercloud? The regulars on FreeNode #scala
have submitted patches, which are only a little slower than the
current implementation and definitely safe.
On Dec 5, 11:09 am, "Viktor Klang" <[EMAIL PROTECTED]> wrote:
> Yes, I agree, arrays is a lame "corner"-case.
>
> However, my opinion is that the concept of array as in "contigous memory
> area that is efficient for a processor to process" is an
> implementation/optimization feature, and not a language feature.
> While I fully agree that many programmers couldn't live without the precious
> array, I truely hope that a VM could use them "under the hood" to provide
> better performance for certain List use-cases.
>
> In Java, you could probably manage very well with only Buffer and ArrayList.
>
> Scala Lists are immutable, and can therefor be shared freely.
>
> What's your take on this?
>
> Cheers,
> Viktor
>
>
>
> On Thu, Dec 4, 2008 at 11:33 PM, hlovatt <[EMAIL PROTECTED]> wrote:
>
> > The Scala case classes only do the simple cases, consider:
>
> > object Main {
> > case class Foo( values : Array[Int] ) {
> > var anotherValue : Int = 1
> > }
>
> > def main( args : Array[String] ) = {
> > val a = Array( 1, 2, 3 )
> > val f1 = Foo( a )
> > println( f1.values.toString )
> > a(0) = 2
> > println( f1.values.toString )
> > val f2 = Foo( a )
> > f2.anotherValue = 2
> > println( f1 == f2 )
> > }
> > }
>
> > It prints:
>
> > Array(1, 2, 3)
> > Array(2, 2, 3)
> > true
>
> > So no it doesn't deep copy arguments and it also only uses the fields
> > of the constructor for equals, hash, etc. and not any other fields.
> > The facilities in PEC solve both these problems (http://
> > pec.dev.java.net/compile/javadoc/pec/compile/immutable/
> > AbstractImmutable.html<http://pec.dev.java.net/compile/javadoc/pec/compile/immutable/Abstrac...>
> > ).
>
> > On Dec 5, 9:10 am, "Michael Lee" <[EMAIL PROTECTED]> wrote:
> > > Does Scalar support the defensive copy of mutable attributes? For
> > examples,
> > > if the constructor takes in in an array, does it automatically 'clone'
> > the
> > > array for internal attribute? How about 'get' method?
> > > Thanks in advance.
>
> > > On Thu, Dec 4, 2008 at 4:05 PM, Viktor Klang <[EMAIL PROTECTED]>
> > wrote:
> > > > What I do in Scala:
>
> > > > case class Person(val firstName : String, val lastName : String)
>
> > > > then I get correct equals, hashCode, a toString and pattern-matching
> > and a
> > > > concise creation syntax:
>
> > > > val person = Person("Keith","Haber")
>
> > > > So instead of 30+ lines of Java, I get 1 line of Scala, with more
> > > > functionality ;)
>
> > > > </endShamelessPlug>
>
> > > > :)
>
> > > > On Thu, Dec 4, 2008 at 5:45 PM, Keith Haber <[EMAIL PROTECTED]> wrote:
>
> > > >> When I want to make an immutable type with a lot of attributes. I
> > > >> generally like to use a static inner class as a builder object.
> > > >> Here's an example with just two attributes.
>
> > > >> public final class Person{
>
> > > >> private final String firstName;
> > > >> private final String lastName;
>
> > > >> public Person(String firstName, String lastName){
> > > >> super();
> > > >> this.firstName = firstName;
> > > >> this.lastName = lastName;
> > > >> }
>
> > > >> public String getFirstName(){return firstName;}
> > > >> public String getLastName(){return lastName;}
>
> > > >> public static class Builder {
> > > >> private String firstName;
> > > >> private String lastName;
>
> > > >> public Builder setFirstName(String firstName){
> > > >> this.firstName = firstName;
> > > >> return this;
> > > >> }
>
> > > >> public Builder setLastName(String lastName){
> > > >> this.lastName = lastName;
> > > >> return this;
> > > >> }
>
> > > >> public Person newPerson(){
> > > >> return new Person(firstName, lastName);
> > > >> }
> > > >> }
>
> > > >> }
>
> > > >> Then in my client code, I would do:
>
> > > >> Person keith = new Person.Builder().setFirstName
> > > >> ("Keith").setLastName("Haber").newPerson();
>
> > > >> Or if I need to instantiate a lot of similar objects, I can hang on to
> > > >> my Builder object. (Could be handy for constructing relatives, I
> > > >> suppose.)
>
> > > >> A nice thing about this approach is that I get the benefit of readable
> > > >> setters instead of working with long lists of meticulously ordered
> > > >> constructor arguments (not so big a deal with two attributes, but very
> > > >> helpful when working with six or more attributes), but my immutable
> > > >> objects don't have setters at all.
>
> > > >> And by making the builder class a static inner class, it's obvious
> > > >> which builder classes go with which immutable types -- it's always
> > > >> named <immutable type name>.Builder.
>
> > > >> In episode 219 they talked about objects having a "construct phase"
> > > >> with setters and a "use phase" when the object construction is
> > > >> "finished." To my mind this approach is reasonably close to that
> > > >> idea.
>
> > > >> Keith
>
> > > >> On Dec 3, 10:58 pm, hlovatt <[EMAIL PROTECTED]> wrote:
> > > >> > In 219 there was a long discussion about setting up an object and
> > then
> > > >> > making it immutable. There are a couple of ways of doing this in
> > Java
> > > >> > already:
>
> > > >> > public class FooArgs {
> > > >> > public int x = 1; // 1 is default
> > > >> > public int y = 2;
> > > >> > public int z = 3;
> > > >> > ...
>
> > > >> > }
>
> > > >> > public class Foo {
> > > >> > public Foo( FooArgs args ) { ... }
> > > >> > ...
>
> > > >> > }
>
> > > >> > Foo foo = new Foo( new FooArgs() {{ x = 2 }} );
>
> > > >> > Another option is an immutable and mutable versions that inherit
> > from
> > > >> > a common base and implement a standard conversion interface. First
> > the
> > > >> > standard interface:
>
> > > >> > public interface ImmutableValueConversions {
> > > >> > Immutable toImmutable() throws IllegalStateException;
> > > >> > Value toValue();
>
> > > >> > }
>
> > > >> > Below is an integer example that uses an abstract class as the base
> > of
> > > >> > the hierarchy. You can also use interfaces. The abstract class is:
>
> > > >> > 8:public abstract class AbstractInteger extends AbstractValue
> > > >> > 9: implements ImmutableValueConversions, InstanceFactory {
> > > >> > 10: public abstract int getValue();
> > > >> > 11:
> > > >> > 12: public abstract AbstractInteger instanceOfSelf( int value
> > );
> > > >> > 13:
> > > >> > 14: public AbstractInteger add( final int rhs ) {
> > > >> > 15: return instanceOfSelf( getValue() + rhs );
> > > >> > 16: }
> > > >> > 17:}
>
> > > >> > Then the immutable version:
>
> > > >> > 9:public final class ImmutableInteger2 extends AbstractInteger
> > > >> > 10: implements Immutable {
> > > >> > 11: private final int value;
> > > >> > 12:
> > > >> > 13: public ImmutableInteger2( final int value ) {
> > > >> > 14: this.value = value;
> > > >> > 15: }
> > > >> > 16:
> > > >> > 17: public int getValue() {
> > > >> > 18: return value;
> > > >> > 19: }
> > > >> > 20:
> > > >> > 21: public Immutable toImmutable() {
> > > >> > 22: return this;
> > > >> > 23: }
> > > >> > 24:
> > > >> > 25: public Value toValue() {
> > > >> > 26: return new ValueInteger( value );
> > > >> > 27: }
> > > >> > 28:
> > > >> > 29: public AbstractInteger instanceOfSelf( final int value ) {
> > > >> > 30: return new ImmutableInteger2( value );
> > > >> > 31: }
> > > >> > 38:}
>
> > > >> > And the value version:
>
> > > >> > 9:public final class ValueInteger extends AbstractInteger {
> > > >> > 10: // Not final, this is the value version
> > > >> > 11: private int value;
> > > >> > 12:
> > > >> > 13: public ValueInteger( final int value ) {
> > > >> > 14: this.value = value;
> > > >> > 15: }
> > > >> > 16:
> > > >> > 17: public int getValue() {
> > > >> > 18: return value;
> > > >> > 19: }
> > > >> > 20:
> > > >> > 21: // Setter, this is the value version!
> > > >> > 22: public void setValue( final int value ) {
> > > >> > 23: this.value = value;
> > > >> > 24: }
> > > >> > 25:
> > > >> > 26: public Immutable toImmutable() {
> > > >> > 27: return new ImmutableInteger2( value );
> > > >> > 28: }
> > > >> > 29:
> > > >> > 30: public Value toValue() {
> > > >> > 31: return new ValueInteger( value );
> > > >> > 32: }
> > > >> > 33:
> > > >> > 34: public AbstractInteger instanceOfSelf( final int value ) {
> > > >> > 35: return new ValueInteger( value );
> > > >> > 36: }
> > > >> > 37:
> > > >> > 38: // Set and add combined (+=), this is the value version!
> > > >> > 39: public ValueInteger setAdd( final int rhs ) {
> > > >> > 40: value += rhs;
> > > >> > 41: return this;
> > > >> > 42: }
> > > >> > 49:}
>
> > > >> > Then you can use these classes like this:
>
> > > >> > ImmutableInteger i = (ImmutableInteger)( new
> > ValueInteger().setValue
> > > >> > ( 2 ).toValue() );
>
> > > >> > My own pet project, PEC, is an extensible compiler that can enforce
> > > >> > patterns, the above immutable pattern can be enforced. More details
> > > >> > from:
>
> > > >> > http://pec.dev.java.net/nonav/frontpage.html
>
> > > >> > What do others do?
>
> > > > --
> > > > Viktor Klang
> > > > Senior Systems Analyst
>
> --
> Viktor Klang
> Senior Systems Analyst
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "The
Java Posse" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/javaposse?hl=en
-~----------~----~----~----~------~----~------~--~---