« Return to Thread: idea: val x, y {... x = ... y = ...}

Re: idea: val x, y {... x = ... y = ...}

by Rob Dickens-2 :: Rate this Message:

Reply to Author | View in Thread

First of all, a big thanks for all the responses.

The point you might have missed, Mark, was to confine the scope of all local vals to where they're used (without having to introduce all those shadow vals). So, taking the idea of nested functions to something of an extreme, I got,

  // scala version, take 2
  def complete(context: Context): Boolean = {
    def complete1(elapsedSecs: Int) =
      if (elapsedSecs > flightSecs) true
      else complete2(elapsedSecs.toDouble/flightSecs)

    def complete2(progress: Double) = 
      complete3(range*progress, 
                (4*range*(progress - progress*progress)).toInt)

    def complete3(d: Double, z: Int) = 
      complete4(frX + (d*kX).toInt, frY + (d*kY).toInt, z)

    def complete4(x: Int, y: Int, z: Int) = {
      context.driver.look(separation, x, y, z)
      false
    }

    complete1((System.currentTimeMillis - startMillis/1000).toInt)
  }

And once again, for comparison:

  // scalax version
  def complete(context: Context): Boolean = {
    val x, y, z {
      val progress = {
        val elapsedSecs = (System.currentTimeMillis - startMillis/1000).toInt
        if (elapsedSecs > flightSecs) return true
        elapsedSecs.toDouble/flightSecs
      } {
        val d = range*progress
        x = frX + (d*kX).toInt
        y = frY + (d*kY).toInt
      }
      z = (4*range*(progress - progress*progress)).toInt
    }
    context.driver.look(separation, x, y, z)
    false
  }

One observation about the scala version is that you end up not being able to take advantage of type-inference, since the vals now appear as arguments. Another is that, after all that, there's no confinement of the scope of the functions themselves!

Anyway, back tomorrow.

2009/5/21 Josh Suereth <joshua.suereth@...>
I'd like it even better with nested function instead of private!


def complete(context: Context): Boolean = {
  def completeImpl(context: Context, elapsedSecs: Int) {
    val progress = elapsedSecs.toDouble/flightSecs
    val d = range*progress
    val x = frX + (d*kX).toInt
    val y = frY + (d*kY).toInt
    val z = (4*range*(progress - progress*progress)).toInt
    context.driver.look(separation, x, y, z)
  }
  val elapsedSecs = (System.currentTimeMillis - startMillis/1000).toInt
  if (elapsedSecs > flightSecs) {
    true
  } else {
    completeImpl(context, elapsedSecs)
    false
  }
}

Why?  completeImpl is an implementation detail of the complete function.  Anyway, I do think your solution outlined nicely an alternative method regardless.  Just thought I'd poke my "nested functions are better than private functions in situation x" $.02

-Josh


On Thu, May 21, 2009 at 1:04 PM, Mark Harrah <harrah@...> wrote:
Maybe I'm missing the point, but this looks equivalent and cleaner:

def complete(context: Context): Boolean = {
 val elapsedSecs = (System.currentTimeMillis - startMillis/1000).toInt
 if (elapsedSecs > flightSecs)
   true
 else {
   completeImpl(context, elapsedSecs)
   false
 }
}
private def completeImpl(context: Context, elapsedSecs: Int) {
 val progress = elapsedSecs.toDouble/flightSecs
 val d = range*progress
 val x = frX + (d*kX).toInt
 val y = frY + (d*kY).toInt
 val z = (4*range*(progress - progress*progress)).toInt
 context.driver.look(separation, x, y, z)
}


-Mark

On Thursday 21 May 2009, Rob Dickens wrote:
> Okay, here's something more realistic - a method that gets called
> periodically, in this case to make something 'look' at the next point in
> space:
>   // scala version
>   def complete(context: Context): Boolean = {
>     val (x, y, z) = {
>       val progress = {
>         val elapsedSecs = (System.currentTimeMillis -
> startMillis/1000).toInt
>         if (elapsedSecs > flightSecs) return true
>         elapsedSecs.toDouble/flightSecs
>       }
>       val (_x, _y) = {
>         val d = range*progress
>         (frX + (d*kX).toInt, frY + (d*kY).toInt)
>       }
>       val _z = (4*range*(progress - progress*progress)).toInt
>       (_x, _y, _z)
>     }
>     context.driver.look(separation, x, y, z)
>     false
>   }
>
>   // scalax version
>   def complete(context: Context): Boolean = {
>     val x, y, z {
>       val progress = {
>         val elapsedSecs = (System.currentTimeMillis -
> startMillis/1000).toInt
>         if (elapsedSecs > flightSecs) return true
>         elapsedSecs.toDouble/flightSecs
>       } {
>         val d = range*progress
>         x = frX + (d*kX).toInt
>         y = frY + (d*kY).toInt
>       }
>       z = (4*range*(progress - progress*progress)).toInt
>     }
>     context.driver.look(separation, x, y, z)
>     false
>   }
>
> 2009/5/21 Ricky Clarkson <ricky.clarkson@...>
>
> > point {
> >   val a = 1 + 2
> >  val b = 3 + 4
> >  (a + 1, a + b, a - b)
> > }
> >
> > I know it looks like I'm just being picky, but I'm encouraging you to
> > give a use case.  Perhaps this is one:
> >
> > val (x, y, z) = {
> >  val a = 1 + 2
> >   val _x = a + 5
> >  val _y = _x + 3
> >  val _z = _y * 4
> >  (_x, _y, _z)
> > }
> >
> > 2009/5/21 Rob Dickens <arctic.bob@...>:
> > > So maybe I should have written,
> > > def scalaVersion() {
> > >   val (x, y, z) = {
> > >     val a = 1 + 2
> > >     val _x = a + 1
> > >     val b = 3 + 4
> > >     val _y = a + b
> > >     val _z = a - b
> > >     (_x, _y, _z)
> > >   }
> > >   point(x, y, z)
> > > }
> > > 2009/5/21 Ricky Clarkson <ricky.clarkson@...>
> > >
> > >> val (x, y, z) = {
> > >>  val a = 1 + 2
> > >>  val b = 3 + 4
> > >>  (a + 1, a + b, a - b)
> > >> }
> > >>
> > >> 2009/5/21 Rob Dickens <arctic.bob@...>:
> > >> > Dear Martin and All,
> > >> > One good thing Java still has going for it IMO is its ability,
> > >> > thanks
> >
> > to
> >
> > >> > its
> > >> > 'blank finals', always to let you confine the scope of local
> > >> > variables to
> > >> > where they're used - thus resulting in more maintainable code.
> > >> > For example,
> > >> > void javaVersion() {
> > >> >   final int x, y, z; {
> > >> >     final int a = 1 + 2;
> > >> >     x = a + 1;
> > >> >     final int b = 3 + 4;
> > >> >     y = a + b;
> > >> >     z = a - b;
> > >> >   }
> > >> >   point(x, y, z);
> > >> > }
> > >> > To my knowledge, this is currently best translated as,
> > >> > def scalaVersion() {
> > >> >   val (x, y, z) = {
> > >> >     val a = 1 + 2
> > >> >     val _x = a + 1
> > >> >     val b = 3 + 4
> > >> >     (_x, a + b, a - b)
> > >> >   }
> > >> >   point(x, y, z)
> > >> > }
> > >> > Note the requirement for the shadow val, _x.
> > >> > Assuming it were feasible to support, and imagining cases with more
> > >> > complex
> > >> > expressions, wouldn't the following syntax be more agreeable?
> > >> > def scalaxVersion() {
> > >> >   val x, y, z {
> > >> >     val a = 1 + 2
> > >> >     x = a + 1
> > >> >     val b = 3 + 4
> > >> >     y = a + b
> > >> >     z = a - b
> > >> >   }
> > >> >   point(x, y, z)
> > >> > }
> > >> > --
> > >> > Rob, Lafros.com




 « Return to Thread: idea: val x, y {... x = ... y = ...}