Quantcast

Temporary Values in Constructors Retained As Fields

classic Classic list List threaded Threaded
28 messages Options
12
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Temporary Values in Constructors Retained As Fields

Randall R Schulz-2
Hi,

I'm working through Programming in Scala and when I came to the Rational
number example, I found myself wondering about the "private val g"
defined to hold the result of the greatest common divisor calculation
used to reduce the arguments to the normal form. This value is used
twice, so is computed once and stored in a private val so both the
numerator and the denominator can be divided by it. It is never needed
after the reduced numerator and denominator are computed:

-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
/*
 * Copyright (C) 2007-2008 Artima, Inc. All rights reserved.
 */
class Rational(n: Int, d: Int) {

  require(d != 0)

  private val g = gcd(n.abs, d.abs)
  val numer = n / g
  val denom = d / g

  // ...

  private def gcd(a: Int, b: Int): Int =
    if (b == 0) a else gcd(b, a % b)
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


When I compile this and dump it with javap, I find that the private val
g is part of the class:

-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
% javap -private !-2:$
javap -private Rational
Compiled from "Rational.scala"
public class Rational extends java.lang.Object implements
scala.ScalaObject{
    private final int denom;
    private final int numer;
    private final int g;
    ...
    private int g();
    ...
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


Now if Rational is going to be used in a way that produces large
populations, this wasted field is undesirable. So the question is: How
does one avoid it? I puzzled over this for quite a while and couldn't
figure out how, but I'm a Scala neophyte, at best, so this failure may
just reflect the insufficiency of my knowledge.

What's the answer? Is the only way out calling gcd(...) twice?


Randall Schulz
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Jorge Ortiz
Try:

  val (numer, denom) = {
    val g = gcd(n.abs, d.abs)
    (n / g, d / g)
  }

--j

On Sun, Mar 15, 2009 at 10:23 AM, Randall R Schulz <[hidden email]> wrote:
Hi,

I'm working through Programming in Scala and when I came to the Rational
number example, I found myself wondering about the "private val g"
defined to hold the result of the greatest common divisor calculation
used to reduce the arguments to the normal form. This value is used
twice, so is computed once and stored in a private val so both the
numerator and the denominator can be divided by it. It is never needed
after the reduced numerator and denominator are computed:

-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
/*
 * Copyright (C) 2007-2008 Artima, Inc. All rights reserved.
 */
class Rational(n: Int, d: Int) {

 require(d != 0)

 private val g = gcd(n.abs, d.abs)
 val numer = n / g
 val denom = d / g

 // ...

 private def gcd(a: Int, b: Int): Int =
   if (b == 0) a else gcd(b, a % b)
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


When I compile this and dump it with javap, I find that the private val
g is part of the class:

-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
% javap -private !-2:$
javap -private Rational
Compiled from "Rational.scala"
public class Rational extends java.lang.Object implements
scala.ScalaObject{
   private final int denom;
   private final int numer;
   private final int g;
   ...
   private int g();
   ...
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


Now if Rational is going to be used in a way that produces large
populations, this wasted field is undesirable. So the question is: How
does one avoid it? I puzzled over this for quite a while and couldn't
figure out how, but I'm a Scala neophyte, at best, so this failure may
just reflect the insufficiency of my knowledge.

What's the answer? Is the only way out calling gcd(...) twice?


Randall Schulz

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Jorge Ortiz
Neverming, it seems that doesn't actually help.

Stick with factories and assert gcd == 1.

--j

On Sun, Mar 15, 2009 at 11:38 AM, Jorge Ortiz <[hidden email]> wrote:
Try:

  val (numer, denom) = {

    val g = gcd(n.abs, d.abs)
    (n / g, d / g)
  }

--j


On Sun, Mar 15, 2009 at 10:23 AM, Randall R Schulz <[hidden email]> wrote:
Hi,

I'm working through Programming in Scala and when I came to the Rational
number example, I found myself wondering about the "private val g"
defined to hold the result of the greatest common divisor calculation
used to reduce the arguments to the normal form. This value is used
twice, so is computed once and stored in a private val so both the
numerator and the denominator can be divided by it. It is never needed
after the reduced numerator and denominator are computed:

-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
/*
 * Copyright (C) 2007-2008 Artima, Inc. All rights reserved.
 */
class Rational(n: Int, d: Int) {

 require(d != 0)

 private val g = gcd(n.abs, d.abs)
 val numer = n / g
 val denom = d / g

 // ...

 private def gcd(a: Int, b: Int): Int =
   if (b == 0) a else gcd(b, a % b)
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


When I compile this and dump it with javap, I find that the private val
g is part of the class:

-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
% javap -private !-2:$
javap -private Rational
Compiled from "Rational.scala"
public class Rational extends java.lang.Object implements
scala.ScalaObject{
   private final int denom;
   private final int numer;
   private final int g;
   ...
   private int g();
   ...
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


Now if Rational is going to be used in a way that produces large
populations, this wasted field is undesirable. So the question is: How
does one avoid it? I puzzled over this for quite a while and couldn't
figure out how, but I'm a Scala neophyte, at best, so this failure may
just reflect the insufficiency of my knowledge.

What's the answer? Is the only way out calling gcd(...) twice?


Randall Schulz


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Jan Lohre
In reply to this post by Randall R Schulz-2
The following should work:

val (numer,denom) = {
  val g = gcd(n.abs, d.abs)
  (n/g,d/g)
}

I did not validate it though.

Kind regards,
Jan

2009/3/15 Randall R Schulz <[hidden email]>
Hi,

I'm working through Programming in Scala and when I came to the Rational
number example, I found myself wondering about the "private val g"
defined to hold the result of the greatest common divisor calculation
used to reduce the arguments to the normal form. This value is used
twice, so is computed once and stored in a private val so both the
numerator and the denominator can be divided by it. It is never needed
after the reduced numerator and denominator are computed:

-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
/*
 * Copyright (C) 2007-2008 Artima, Inc. All rights reserved.
 */
class Rational(n: Int, d: Int) {

 require(d != 0)

 private val g = gcd(n.abs, d.abs)
 val numer = n / g
 val denom = d / g

 // ...

 private def gcd(a: Int, b: Int): Int =
   if (b == 0) a else gcd(b, a % b)
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


When I compile this and dump it with javap, I find that the private val
g is part of the class:

-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
% javap -private !-2:$
javap -private Rational
Compiled from "Rational.scala"
public class Rational extends java.lang.Object implements
scala.ScalaObject{
   private final int denom;
   private final int numer;
   private final int g;
   ...
   private int g();
   ...
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


Now if Rational is going to be used in a way that produces large
populations, this wasted field is undesirable. So the question is: How
does one avoid it? I puzzled over this for quite a while and couldn't
figure out how, but I'm a Scala neophyte, at best, so this failure may
just reflect the insufficiency of my knowledge.

What's the answer? Is the only way out calling gcd(...) twice?


Randall Schulz

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Dimitris Andreou
In reply to this post by Jorge Ortiz
You mean that there is no way to use local (temporary) vars in primary
constructors?? This sounds bad.

O/H Jorge Ortiz έγραψε:

> Neverming, it seems that doesn't actually help.
>
> Stick with factories and assert gcd == 1.
>
> --j
>
> On Sun, Mar 15, 2009 at 11:38 AM, Jorge Ortiz <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     Try:
>
>       val (numer, denom) = {
>
>         val g = gcd(n.abs, d.abs)
>         (n / g, d / g)
>       }
>
>     --j
>
>
>     On Sun, Mar 15, 2009 at 10:23 AM, Randall R Schulz
>     <[hidden email] <mailto:[hidden email]>> wrote:
>
>         Hi,
>
>         I'm working through Programming in Scala and when I came to
>         the Rational
>         number example, I found myself wondering about the "private val g"
>         defined to hold the result of the greatest common divisor
>         calculation
>         used to reduce the arguments to the normal form. This value is
>         used
>         twice, so is computed once and stored in a private val so both the
>         numerator and the denominator can be divided by it. It is
>         never needed
>         after the reduced numerator and denominator are computed:
>
>         -==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
>         /*
>          * Copyright (C) 2007-2008 Artima, Inc. All rights reserved.
>          */
>         class Rational(n: Int, d: Int) {
>
>          require(d != 0)
>
>          private val g = gcd(n.abs, d.abs)
>          val numer = n / g
>          val denom = d / g
>
>          // ...
>
>          private def gcd(a: Int, b: Int): Int =
>            if (b == 0) a else gcd(b, a % b)
>         }
>         -==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
>
>
>         When I compile this and dump it with javap, I find that the
>         private val
>         g is part of the class:
>
>         -==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
>         % javap -private !-2:$
>         javap -private Rational
>         Compiled from "Rational.scala"
>         public class Rational extends java.lang.Object implements
>         scala.ScalaObject{
>            private final int denom;
>            private final int numer;
>            private final int g;
>            ...
>            private int g();
>            ...
>         }
>         -==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
>
>
>         Now if Rational is going to be used in a way that produces large
>         populations, this wasted field is undesirable. So the question
>         is: How
>         does one avoid it? I puzzled over this for quite a while and
>         couldn't
>         figure out how, but I'm a Scala neophyte, at best, so this
>         failure may
>         just reflect the insufficiency of my knowledge.
>
>         What's the answer? Is the only way out calling gcd(...) twice?
>
>
>         Randall Schulz
>
>
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

David MacIver
In reply to this post by Randall R Schulz-2
2009/3/15 Randall R Schulz <[hidden email]>:
> Now if Rational is going to be used in a way that produces large
> populations, this wasted field is undesirable. So the question is: How
> does one avoid it? I puzzled over this for quite a while and couldn't
> figure out how, but I'm a Scala neophyte, at best, so this failure may
> just reflect the insufficiency of my knowledge.
>
> What's the answer? Is the only way out calling gcd(...) twice?

private[this] val stuff = ...

private variables can in theory escape the scope of the current object
as they're accessible to other instances of the same class. Therefore
they get made fields (in principle you should be able to tell if this
is neccessary and the compiler should be able to avoid it. But this
doesn't happen). private[this] ones are guaranteed to never escape so
will be made fields only if it's needed.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Jorge Ortiz
I tried that. Reality does not agree with you:

$ cat Rational.scala
class Rational(n: Int, d: Int) {
  require(d != 0)

  private[this] val g = gcd(n.abs, d.abs)
  val numer = n / g
  val denom = d / g

  private def gcd(a: Int, b: Int): Int =
   if (b == 0) a else gcd(b, a % b)
}
$ scalac Rational.scala
$ javap -private Rational
Compiled from "Rational.scala"
public class Rational extends java.lang.Object implements scala.ScalaObject{
    private final int denom;
    private final int numer;
    private final int g;
    public Rational(int, int);
    private int gcd(int, int);
    public int denom();
    public int numer();
    public int $tag()       throws java.rmi.RemoteException;
}

--j

On Sun, Mar 15, 2009 at 12:03 PM, David MacIver <[hidden email]> wrote:
2009/3/15 Randall R Schulz <[hidden email]>:
> Now if Rational is going to be used in a way that produces large
> populations, this wasted field is undesirable. So the question is: How
> does one avoid it? I puzzled over this for quite a while and couldn't
> figure out how, but I'm a Scala neophyte, at best, so this failure may
> just reflect the insufficiency of my knowledge.
>
> What's the answer? Is the only way out calling gcd(...) twice?

private[this] val stuff = ...

private variables can in theory escape the scope of the current object
as they're accessible to other instances of the same class. Therefore
they get made fields (in principle you should be able to tell if this
is neccessary and the compiler should be able to avoid it. But this
doesn't happen). private[this] ones are guaranteed to never escape so
will be made fields only if it's needed.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Randall R Schulz-2
In reply to this post by Jan Lohre
On Sunday March 15 2009, Jan Lohre wrote:

> The following should work:
>
> val (numer,denom) = {
>   val g = gcd(n.abs, d.abs)
>   (n/g,d/g)
> }
>
> I did not validate it though.
>
> Kind regards,
> Jan

Keeping in mind that the point of the exercise is to minimize
unnecessary storage within the representation, this is not an
improvement, since now you're dragging a Tuple around!

To wit:

-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
class Rational(n: Int, d: Int) {

  require(d != 0)

  val (numerator, denomator) = {
    val g = gcd(n.abs, d.abs)
    (n/g,d/g)
  }

  private def gcd(a: Int, b: Int): Int =
    if (b == 0) a else gcd(b, a % b)
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-

% javap -private Rational
Compiled from "Rational.scala"
public class Rational extends java.lang.Object implements
scala.ScalaObject{
    private final int denomator;
    private final int numerator;
    private final scala.Tuple2 x$1;
    public Rational(int, int);
    private int gcd(int, int);
    public int denomator();
    public int numerator();
    public int $tag()       throws java.rmi.RemoteException;
}


Definite step backwards!


Randall Schulz
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Randall R Schulz-2
In reply to this post by David MacIver
On Sunday March 15 2009, David MacIver wrote:

> 2009/3/15 Randall R Schulz <[hidden email]>:
> > ...
> >
> > What's the answer? Is the only way out calling gcd(...) twice?
>
> private[this] val stuff = ...
>
> private variables can in theory escape the scope of the current
> object as they're accessible to other instances of the same class.
> Therefore they get made fields (in principle you should be able to
> tell if this is neccessary and the compiler should be able to avoid
> it. But this doesn't happen). private[this] ones are guaranteed to
> never escape so will be made fields only if it's needed.


That doesn't change the generated code, other than in the absence of the
private method for accessing the val g:

-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
class Rational(n: Int, d: Int) {

  require(d != 0)

  private[this] val g = gcd(n.abs, d.abs)
  val numer = n / g
  val denom = d / g

  private def gcd(a: Int, b: Int): Int =
    if (b == 0) a else gcd(b, a % b)
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
% javap -private Rational
Compiled from "Rational.scala"
public class Rational extends java.lang.Object implements
scala.ScalaObject{
    private final int denom;
    private final int numer;
    private final int g;
    public Rational(int, int);
    private int gcd(int, int);
    public int denom();
    public int numer();
    public int $tag()       throws java.rmi.RemoteException;
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


Randall Schulz
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Randall R Schulz-2
In reply to this post by Jorge Ortiz
On Sunday March 15 2009, Jorge Ortiz wrote:
> Nevermind, it seems that doesn't actually help.
>
> Stick with factories and assert gcd == 1.
>
> --j

Just to clarify, the idea is to do all the computation requiring
intermediate values in a factory and simply require that the numerator
and denominator are in reduced form in the primary constructor? Of
course, in this case, that would imply two calls to gcd(...), which
would leave you in the same situation as simply calling gcd twice in
the primary constructor (in this particular example). Naturally that's
an incidental matter that would manifest itself differently in
different classes, but any counterpart of gcd that was computationally
very expensive would still pose a problem, if it had to be verified in
the primary constructor. Can primary constuctors be made private?

Alternately could auxiliary constructors work for this, or do vals
defined within auxiliary constructors also contribute state to the
resulting class?


Randall Schulz
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Ismael Juma
In reply to this post by Jorge Ortiz
On Sun, 2009-03-15 at 11:42 -0700, Jorge Ortiz wrote:
> Neverming, it seems that doesn't actually help.

For the ones who haven't checked, the reason why it doesn't help is that
the tuple returned from the block is stored as a synthetic field. It
does help in cases where one needs to use some locals in the process of
computing a single result. e.g.:

  val numer = {
    val g = gcd(n.abs, d.abs)
    n / g
  }

In this case, g is not stored as a field.

Ismael

> Stick with factories and assert gcd == 1.
>
> --j
>
> On Sun, Mar 15, 2009 at 11:38 AM, Jorge Ortiz <[hidden email]>
> wrote:
>         Try:
>        
>           val (numer, denom) = {
>        
>             val g = gcd(n.abs, d.abs)
>        
>             (n / g, d / g)
>           }
>        
>         --j



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Randall R Schulz-2
On Sunday March 15 2009, Ismael Juma wrote:

> On Sun, 2009-03-15 at 11:42 -0700, Jorge Ortiz wrote:
> > Neverming, it seems that doesn't actually help.
>
> For the ones who haven't checked, the reason why it doesn't help is
> that the tuple returned from the block is stored as a synthetic
> field. It does help in cases where one needs to use some locals in
> the process of computing a single result. e.g.:
>
>   val numer = {
>     val g = gcd(n.abs, d.abs)
>     n / g
>   }
>
> In this case, g is not stored as a field.

True, but you're back to calling gcd twice, once to compute the reduced
numerator and once for the denominator.


> Ismael


Randall Schulz
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Jorge Ortiz
In reply to this post by Randall R Schulz-2
Randall,

I'd do something like:

  package foo

  class Rational private[foo](val numer: Int, val denom: Int) {
    require(denom != 0)
  }

  object Rational {
    def apply(n: Int, d: Int): Rational = {
      val g = gcd(n.abs, d.abs)
      new Rational(n / g, d / g)
    }

    def gcd(a: Int, b: Int): Int =
     if (b == 0) a else gcd(b, a % b)
  }

--j

On Sun, Mar 15, 2009 at 12:15 PM, Randall R Schulz <[hidden email]> wrote:
On Sunday March 15 2009, David MacIver wrote:
> 2009/3/15 Randall R Schulz <[hidden email]>:
> > ...
> >
> > What's the answer? Is the only way out calling gcd(...) twice?
>
> private[this] val stuff = ...
>
> private variables can in theory escape the scope of the current
> object as they're accessible to other instances of the same class.
> Therefore they get made fields (in principle you should be able to
> tell if this is neccessary and the compiler should be able to avoid
> it. But this doesn't happen). private[this] ones are guaranteed to
> never escape so will be made fields only if it's needed.


That doesn't change the generated code, other than in the absence of the
private method for accessing the val g:

-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
class Rational(n: Int, d: Int) {

 require(d != 0)

 private[this] val g = gcd(n.abs, d.abs)
 val numer = n / g
 val denom = d / g

 private def gcd(a: Int, b: Int): Int =
   if (b == 0) a else gcd(b, a % b)
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
% javap -private Rational
Compiled from "Rational.scala"
public class Rational extends java.lang.Object implements
scala.ScalaObject{
   private final int denom;
   private final int numer;
   private final int g;
   public Rational(int, int);
   private int gcd(int, int);
   public int denom();
   public int numer();
   public int $tag()       throws java.rmi.RemoteException;
}
-==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-


Randall Schulz

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

David MacIver
In reply to this post by Jorge Ortiz
2009/3/15 Jorge Ortiz <[hidden email]>:
> I tried that. Reality does not agree with you:

Weird. Reality sure used to agree with me on that one. That probably
constitutes a bug.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Russ Paielli-5
In reply to this post by Randall R Schulz-2
Maybe another private function could be used to compute the numerator and denominator, or maybe even a nested function. I didn't try it though.

However, it does seem that you should be able to get what you want without having to call another function. Maybe you could use a nested block, but then I think you may need to make numer and denom vars rather than vals (so they can be declared before the block and changed in the block).

--Russ

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Martin Odersky
In reply to this post by Randall R Schulz-2
There should be an optimization that turns private[this] variables
that are only used for class initialization into constructor-local
variables. It would be relatively easy to do that, I think. But it has
not yet been done.

Cheers

 -- Martin


On Sun, Mar 15, 2009 at 8:15 PM, Randall R Schulz <[hidden email]> wrote:

> On Sunday March 15 2009, David MacIver wrote:
>> 2009/3/15 Randall R Schulz <[hidden email]>:
>> > ...
>> >
>> > What's the answer? Is the only way out calling gcd(...) twice?
>>
>> private[this] val stuff = ...
>>
>> private variables can in theory escape the scope of the current
>> object as they're accessible to other instances of the same class.
>> Therefore they get made fields (in principle you should be able to
>> tell if this is neccessary and the compiler should be able to avoid
>> it. But this doesn't happen). private[this] ones are guaranteed to
>> never escape so will be made fields only if it's needed.
>
>
> That doesn't change the generated code, other than in the absence of the
> private method for accessing the val g:
>
> -==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
> class Rational(n: Int, d: Int) {
>
>  require(d != 0)
>
>  private[this] val g = gcd(n.abs, d.abs)
>  val numer = n / g
>  val denom = d / g
>
>  private def gcd(a: Int, b: Int): Int =
>    if (b == 0) a else gcd(b, a % b)
> }
> -==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
>
>
> -==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
> % javap -private Rational
> Compiled from "Rational.scala"
> public class Rational extends java.lang.Object implements
> scala.ScalaObject{
>    private final int denom;
>    private final int numer;
>    private final int g;
>    public Rational(int, int);
>    private int gcd(int, int);
>    public int denom();
>    public int numer();
>    public int $tag()       throws java.rmi.RemoteException;
> }
> -==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-
>
>
> Randall Schulz
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Paul Phillips-3
In reply to this post by Randall R Schulz-2
On Sun, Mar 15, 2009 at 12:13:01PM -0700, Randall R Schulz wrote:
> Keeping in mind that the point of the exercise is to minimize
> unnecessary storage within the representation

No problem.

class Rational(n: Int, d: Int) {
  require(d != 0)
 
  val numerator   = n/ gcd(n.abs, d.abs)
  val denominator = numerator * d / n

  private def gcd(a: Int, b: Int): Int =
    if (b == 0) a else gcd(b, a % b)
}                                                                              

(Is there a top prize for missing the point?) Until now I hadn't
realized the multiple assignment approach drags in a permanent tuple.  I
would agree this seems like a real problem, but as already pointed out
factory methods are the way for now.

--
Paul Phillips      | Simplicity and elegance are unpopular because
Stickler           | they require hard work and discipline to achieve
Empiricist         | and education to be appreciated.
i'll ship a pulp   |     -- Dijkstra
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Ismael Juma
On Sun, 2009-03-15 at 12:36 -0700, Paul Phillips wrote:
> (Is there a top prize for missing the point?) Until now I hadn't
> realized the multiple assignment approach drags in a permanent tuple.  I
> would agree this seems like a real problem, but as already pointed out
> factory methods are the way for now.

Since everyone seemed to be surprised by this in the #scala IRC channel
and there doesn't seem to be a good reason for it, shall a bug be filed?

Ismael

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

David MacIver
In reply to this post by Martin Odersky
2009/3/15 martin odersky <[hidden email]>:
> There should be an optimization that turns private[this] variables
> that are only used for class initialization into constructor-local
> variables. It would be relatively easy to do that, I think. But it has
> not yet been done.

I was really sure that I'd seen such behaviour in the past, but I
can't seem to find any evidence of it. It's very strange.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Temporary Values in Constructors Retained As Fields

Randall R Schulz-2
In reply to this post by Randall R Schulz-2
On Sunday March 15 2009, Randall R Schulz wrote:

> Hi,
>
> I'm working through Programming in Scala and when I came to the
> Rational number example, I found myself wondering about the "private
> val g" defined to hold the result of the greatest common divisor
> calculation used to reduce the arguments to the normal form. ...
>
> ... I find that the private val g is part of the class ...
>
> What's the answer? Is the only way out calling gcd(...) twice?


Thanks for the analysis and ideas, folks. I learned some new stuff and I
think I know how to handle this general issue now.


Randall Schulz
12
Loading...