#754 once method in const class, getOrElseUpdate in Map, extension methods

Akcelisto Sun 20 Sep 2009

  1. Why exists restriction: once methods must not be declared within a const class?
  2. In Scala exists methods getOrElseUpdate. It's usefull for methods that remember his returns.
    private Str:Pict picts := Str:Pict[:]
    Pict pict(Str name:=""){ picts.getOrUpdate(name,Pict(name)) }
  3. What do you think about "Extension Methods"?
    class StrUtil
    {
      Str truncate(Str s,Int width){...}
    }
    
    // now
    StrUtil.truncate("string",5)
    
    // Extension Methods
    // option 1
    "string".truncate(5)
    // option 2
    "string"..truncate(5)
    // option 3
    "string".^truncate(5)

brian Sun 20 Sep 2009

@Akcelisto - thanks for your feedback!

Why exists restriction: once methods must not be declared within a const class?

Because a once method in a const class isn't necessarily immutable and thread-safe unless we can safely compute the result in an atomic manner. But that requires locks which introduces all sorts of nastiness. So up until now I've just disallowed it (although eventually I'd like to define a safe design so maybe we can have that feature).

In Scala exists methods getOrElseUpdate. It's usefull for methods that remember his returns.

I am open to adding something like that to map. Although it is potentially inefficient since we have to evaluate the default expression no matter. I suspect that Scala makes that parameter a lazy expression? I'd like to hear some other feedback what other people think.

What do you think about "Extension Methods"?

I think that we need this, but I do not want to tackle for 1.0 (I want to let existing feature set settle down). The way I currently like best is how C# does it (with static methods where first param is notated with this keyword):

class StrUtil
{
  static Str truncate(this Str s, Int width) {...}
}

Akcelisto Mon 21 Sep 2009

I suspect that Scala makes that parameter a lazy expression?

Yes. I am not noticed. Second parameter is "call-by-name".

May be so:

//in Map
V getOrUpdate(K key, |->V| value)

// calling
picts.getOrUpdate(name)|,|{Pict(name)}

brian Mon 21 Sep 2009

Good idea. So let's propose this new method on Map:

V getOrAdd(K key, |K->V| val)

Having it pass the key in the function is probably a little more useful and allows it-blocks (which require one parameter):

picts.getOrAdd(name) { Pict(name) }
picts.getOrAdd(name) { Pict(it) }
picts.getOrAdd(name) |name| { Pict(name) }

andy Mon 21 Sep 2009

+1 - that seems useful.

brian Wed 23 Sep 2009

done!

changeset

jodastephen Wed 23 Sep 2009

> Why exists restriction: once methods must not be declared within a const class? > Because a once method in a const class isn't necessarily immutable and thread-safe unless we can safely compute the result in an atomic manner.

You can add a once method equivalent to Java using volatile variables, no locking required. The key thing is that the method should only refer to const instance variables and other constants. That way the result is always the same, so it doesn't matter whether the code gets run more than once (ie. the once keyword simply means that the result should be cached, as per Java String hashCode).

brian Wed 23 Sep 2009

You can add a once method equivalent to Java using volatile variables, no locking required.

True, although as you said there would be no guarantee that the method was truly executed only once without a lock. I think we can live with that.

But we can't really guarantee that the function only references other const instance fields. You might call other once methods or use dynamic invoke.

jodastephen Thu 24 Sep 2009

Instance fields are either const, non-const or once for this discussion. The const ones are fine to call. The non-const ones don't exist (its a const class we're discussing).

The once ones should also be fine - a once field that calls another once field will just cause that field to be initialised.

So, you'd just need to block dynamic invoke, which shouldn't be too hard.

Login or Signup to reply.