Avoiding Scala memory leaks - Scala constructors?

You could do this: val numer = numerator / gcd(numerator. Abs, denominator. Abs) val denom = denominator / gcd(numerator.

Abs, denominator. Abs) Of course you'd have to do the calculation twice. But then optimizations are often a trade-off between memory/space and execution time Maybe there are other ways too, but then the program might get overly complex, and if there's one place where optimization is rarely premature, it's brain power optimization :).

For instance, you could probably do this: val numer = numerator / gcd(numerator. Abs, denominator. Abs) val denom = denominator / (numerator / numer) But it doesn't necessarily make the code more understandable (Note: I didn't actually try this, so use at your own risk.).

You could do this: val numer = numerator / gcd(numerator. Abs, denominator. Abs) val denom = denominator / gcd(numerator.

Abs, denominator. Abs) Of course you'd have to do the calculation twice. But then optimizations are often a trade-off between memory/space and execution time.

Maybe there are other ways too, but then the program might get overly complex, and if there's one place where optimization is rarely premature, it's brain power optimization :). For instance, you could probably do this: val numer = numerator / gcd(numerator. Abs, denominator.

Abs) val denom = denominator / (numerator / numer) But it doesn't necessarily make the code more understandable. (Note: I didn't actually try this, so use at your own risk. ).

Thanks, your second solution works (though I haven't done any rigorous testing) and does get rid of any superfluous fields with negligible overhead. – Flaviu Cipcigan Aug 2 '09 at 16:05.

A companion object can provide the flexibility you need. It can define a "static" factory methods that replace the constructor. Object Rational{ def apply(numerator: Int, denominator: Int) = { def gcd(a: Int, b: Int): Int = if(b == 0) a else gcd(b, a % b) val g = gcd(numerator, denominator) new Rational(numerator / g, denominator / g) } } class Rational(numerator: Int, denominator: Int) { require(denominator!

= 0) override def toString = numerator + "/" + denominator // other methods go here, neither access g } val r = Rational(10,200) In the scope of the factory method g can be calculate and used to the derive the two constructor values.

1 Thanks for the answer, I was thinking of a factory as well, but that would add a couple of complications. For example, a user could invoke the object's constructor (e.g. New Rational(10,20)) and in the process create an invalid rational. One could add an require(gcd(numerator, denominator) == 1) to the constructor or make the class constructor private and oblige the users to use the factory.

I am not sure what would be best... a factory does seem a bit overkill for a Rational :) – Flaviu Cipcigan Aug 2 '09 at 16:15 2 Note that since the factory method's name is apply, it can be called like this: Rational(10, 20). – Alexey Romanov Aug 2 '09 at 21:57.

There's a small problem with Thomas Jung's example; it still allows you to create a Rational object with a common term in the numerator and denominator - if you create the Rational object using 'new' yourself, instead of via the companion object: val r = new Rational(10, 200) // Oops! Creating a Rational with a common term You can avoid this by requiring client code to always use the companion object to create a Rational object, by making the implicit constructor private: class Rational private (numerator: Int, denominator: Int) { // ... }.

You could do this: object Rational { def gcd(a: Int, b: Int): Int = if(b == 0) a else gcd(b, a % b) } class Rational private (n: Int, d: Int, g: Int) { require(d! = 0) def this(n: Int, d: Int) = this(n, d, Rational. Gcd(n.

Abs, d. Abs)) val numer = n / g val denom = d / g override def toString = numer + "/" + denom }.

... actually, I don't see how this constitutes a "memory leak". You declare a final field within the scope of the class instance, and are then apparently surprised that it "hangs around". What behaviour did you expect?

Am I missing something here?

2 The problem is that there's no clean way to define a temporary variable that's only used during the construction of the object, as you could with a Java constructor. – Cody Casterline Aug 28 '10 at 18:59 2 This is not formally a memory leak, since it is still reachable from global or local variables (which is why the GC doesn't clean it up). It is certainly a "leak" in the informal sense that it's data that live on even though you will never need it.

– Malvolio Jan 9 at 23:58 I think the choice of title is a bit misleading. – ziggystar Mar 30 at 8:51.

I came across this article which you might find useful: daily-scala.blogspot.com/2010/02/tempora... It seems you could write this: class Rational(numerator: Int, denominator: Int) { require(denominator! = 0) val (numer,denom) = { val g = gcd(numerator. Abs, denominator.

Abs) (numerator/g, denominator/g) } override def toString = numer + "/" + denom private def gcd(a: Int, b: Int): Int = if(b == 0) a else gcd(b, a % b) // other methods go here, neither access g }.

Could be like: def g = gcd(numerator. Abs, denominator. Abs) instead of val.

But then optimizations are often a trade-off between memory/space and execution time Maybe there are other ways too, but then the program might get overly complex, and if there's one place where optimization is rarely premature, it's brain power optimization :). For instance, you could probably do this: val numer = numerator / gcd(numerator. Abs) val denom = denominator / (numerator / numer) But it doesn't necessarily make the code more understandable (Note: I didn't actually try this, so use at your own risk.).

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions