This page is no longer maintained — Please continue to the home page at www.scala-lang.org

variable scoping problem with continuations

5 replies
Jim McBeath
Joined: 2009-01-02,
User offline. Last seen 42 years 45 weeks ago.

If you load the below test into the REPL (either 2.8.1 or 2.9.0.RC1;
use "scala -P:continuations:enable") and evaluate Test.test, it gives
this output:

initial x=3
final x=6561
initial y=3
final y=3

The final y value should be 6561 rather than 3.

The same happens if you compile it and run
"scala -P:continuations:enable Test" from the command line.

The only difference between x and y is that the initial assignment to y
is done by a call to a suspendable method. If you add a print statement
inside the for loop, it appears to behave correctly while in the loop,
with the value of y stepping up to 9, 81 and 6561, but that updated
value gets lost when the loop exits. If the call to suspendableThree
is assigned to another variable such as z, and then y is set to the
value of z, then the final y value is correct.

Is this a bug, or am I doing something wrong with continuations?

object Test {
import scala.util.continuations._
def test {
reset {
var x = 3
println("initial x="+x)
for (i <- 1 to 3)
x = x*x
println("final x="+x)

var y = suspendableThree
println("initial y="+y)
for (i <- 1 to 3)
y = y*y
println("final y="+y)
}
}
def suspendableThree:Int @suspendable = {
shift { k:((Int)=>Unit) => k(3) }
}

def main(args:Array[String]) = test
}

--
Jim

Tiark Rompf
Joined: 2009-02-18,
User offline. Last seen 42 years 45 weeks ago.
Re: variable scoping problem with continuations

Hey Jim, this looks like a bug. I think it has to do with y being transformed into a Ref object because it is modified from inside the closure that is passed to foreach. Please file a ticket.
- Tiark

On Apr 15, 2011, at 6:27 PM, Jim McBeath wrote:

> If you load the below test into the REPL (either 2.8.1 or 2.9.0.RC1;
> use "scala -P:continuations:enable") and evaluate Test.test, it gives
> this output:
>
> initial x=3
> final x=6561
> initial y=3
> final y=3
>
> The final y value should be 6561 rather than 3.
>
> The same happens if you compile it and run
> "scala -P:continuations:enable Test" from the command line.
>
> The only difference between x and y is that the initial assignment to y
> is done by a call to a suspendable method. If you add a print statement
> inside the for loop, it appears to behave correctly while in the loop,
> with the value of y stepping up to 9, 81 and 6561, but that updated
> value gets lost when the loop exits. If the call to suspendableThree
> is assigned to another variable such as z, and then y is set to the
> value of z, then the final y value is correct.
>
> Is this a bug, or am I doing something wrong with continuations?
>
> object Test {
> import scala.util.continuations._
> def test {
> reset {
> var x = 3
> println("initial x="+x)
> for (i <- 1 to 3)
> x = x*x
> println("final x="+x)
>
> var y = suspendableThree
> println("initial y="+y)
> for (i <- 1 to 3)
> y = y*y
> println("final y="+y)
> }
> }
> def suspendableThree:Int @suspendable = {
> shift { k:((Int)=>Unit) => k(3) }
> }
>
> def main(args:Array[String]) = test
> }
>
> --
> Jim

Luc Duponcheel
Joined: 2008-12-19,
User offline. Last seen 34 weeks 3 days ago.
Re: variable scoping problem with continuations
... interesting ...

it is nearly impossible to try to transalate
this program to a monadic one because of the
usage of vars

... whether encouraging using vars is a good thing is another discussion ...

 def jimMcBeathTest1() {
  import Int_Int_ControlTransformedIdentityMonadObject._
  resetC {
   // ok: this is possible
   var x = 3
   println("initial x = " + x)
   for (i <- 1 to 3) {
    x = x * x
   }
   println("final x = " + x)
   suspendableThree >= { (y: Int) =>
    println("initial y = " + y)
    // ko: no way to change something here
    for (i <- 1 to 3) {
     /* y = y * y */
    }
    println("final y = " + y)
    _return(y)
   }
  }
  def suspendableThree: M[Int] =
   shiftCC { c =>
    c(3)
   }
 }
 def jimMcBeathTest2() {
  import Int_Int_ControlTransformedIdentityMonadObject._
  resetC {
   // ok: this is possible
   var x = 3
   println("initial x = " + x)
   for (i <- 1 to 3) {
    x = x * x
   }
   println("final x = " + x)
   var my = suspendableThree
   // ko: not binding my to anything here
   println("initial y =")
   for { y <- my } yield { println(" " + y) }
   for { y <- my } yield { my = _return(y * y) }
   print("final y =")
   for { y <- my } yield { println(" " + y) }
   my
  }
  def suspendableThree: M[Int] =
   shiftCC { c =>
    c(3)
   }
 }

$ scala com.imaginej.apps.UsingControlMonads
initial x = 3
final x = 6561
initial y = 3
final y = 3
-------
initial x = 3
final x = 6561
initial y =



On Sun, Apr 17, 2011 at 2:14 AM, Tiark Rompf <tiark.rompf@epfl.ch> wrote:
Hey Jim, this looks like a bug. I think it has to do with y being transformed into a Ref object because it is modified from inside the closure that is passed to foreach. Please file a ticket.
- Tiark

On Apr 15, 2011, at 6:27 PM, Jim McBeath wrote:

> If you load the below test into the REPL (either 2.8.1 or 2.9.0.RC1;
> use "scala -P:continuations:enable") and evaluate Test.test, it gives
> this output:
>
> initial x=3
> final x=6561
> initial y=3
> final y=3
>
> The final y value should be 6561 rather than 3.
>
> The same happens if you compile it and run
> "scala -P:continuations:enable Test" from the command line.
>
> The only difference between x and y is that the initial assignment to y
> is done by a call to a suspendable method.  If you add a print statement
> inside the for loop, it appears to behave correctly while in the loop,
> with the value of y stepping up to 9, 81 and 6561, but that updated
> value gets lost when the loop exits.  If the call to suspendableThree
> is assigned to another variable such as z, and then y is set to the
> value of z, then the final y value is correct.
>
> Is this a bug, or am I doing something wrong with continuations?
>
> object Test {
>    import scala.util.continuations._
>    def test {
>        reset {
>            var x = 3
>            println("initial x="+x)
>            for (i <- 1 to 3)
>                x = x*x
>            println("final x="+x)
>
>            var y = suspendableThree
>            println("initial y="+y)
>            for (i <- 1 to 3)
>                y = y*y
>            println("final y="+y)
>        }
>    }
>    def suspendableThree:Int @suspendable = {
>        shift { k:((Int)=>Unit) => k(3) }
>    }
>
>    def main(args:Array[String]) = test
> }
>
> --
> Jim




--
   __~O
  -\ <,
(*)/ (*)

reality goes far beyond imagination

Tiark Rompf
Joined: 2009-02-18,
User offline. Last seen 42 years 45 weeks ago.
Re: variable scoping problem with continuations
On Apr 17, 2011, at 6:33 PM, Luc Duponcheel wrote:
... interesting ...

it is nearly impossible to try to transalate
this program to a monadic one because of the
usage of vars

Why? This is (more or less) the result of the actual translation:
reify(suspendableThree).map { y0 => var y = y0 println("initial y="+y) for (i <- 1 to 3)
y = y*y
println("final y="+y) }
- Tiark


... whether encouraging using vars is a good thing is another discussion ...

 def jimMcBeathTest1() {
  import Int_Int_ControlTransformedIdentityMonadObject._
  resetC {
   // ok: this is possible
   var x = 3
   println("initial x = " + x)
   for (i <- 1 to 3) {
    x = x * x
   }
   println("final x = " + x)
   suspendableThree >= { (y: Int) =>
    println("initial y = " + y)
    // ko: no way to change something here
    for (i <- 1 to 3) {
     /* y = y * y */
    }
    println("final y = " + y)
    _return(y)
   }
  }
  def suspendableThree: M[Int] =
   shiftCC { c =>
    c(3)
   }
 }
 def jimMcBeathTest2() {
  import Int_Int_ControlTransformedIdentityMonadObject._
  resetC {
   // ok: this is possible
   var x = 3
   println("initial x = " + x)
   for (i <- 1 to 3) {
    x = x * x
   }
   println("final x = " + x)
   var my = suspendableThree
   // ko: not binding my to anything here
   println("initial y =")
   for { y <- my } yield { println(" " + y) }
   for { y <- my } yield { my = _return(y * y) }
   print("final y =")
   for { y <- my } yield { println(" " + y) }
   my
  }
  def suspendableThree: M[Int] =
   shiftCC { c =>
    c(3)
   }
 }

$ scala com.imaginej.apps.UsingControlMonads
initial x = 3
final x = 6561
initial y = 3
final y = 3
-------
initial x = 3
final x = 6561
initial y =



On Sun, Apr 17, 2011 at 2:14 AM, Tiark Rompf <tiark.rompf@epfl.ch> wrote:
Hey Jim, this looks like a bug. I think it has to do with y being transformed into a Ref object because it is modified from inside the closure that is passed to foreach. Please file a ticket.
- Tiark

On Apr 15, 2011, at 6:27 PM, Jim McBeath wrote:

> If you load the below test into the REPL (either 2.8.1 or 2.9.0.RC1;
> use "scala -P:continuations:enable") and evaluate Test.test, it gives
> this output:
>
> initial x=3
> final x=6561
> initial y=3
> final y=3
>
> The final y value should be 6561 rather than 3.
>
> The same happens if you compile it and run
> "scala -P:continuations:enable Test" from the command line.
>
> The only difference between x and y is that the initial assignment to y
> is done by a call to a suspendable method.  If you add a print statement
> inside the for loop, it appears to behave correctly while in the loop,
> with the value of y stepping up to 9, 81 and 6561, but that updated
> value gets lost when the loop exits.  If the call to suspendableThree
> is assigned to another variable such as z, and then y is set to the
> value of z, then the final y value is correct.
>
> Is this a bug, or am I doing something wrong with continuations?
>
> object Test {
>    import scala.util.continuations._
>    def test {
>        reset {
>            var x = 3
>            println("initial x="+x)
>            for (i <- 1 to 3)
>                x = x*x
>            println("final x="+x)
>
>            var y = suspendableThree
>            println("initial y="+y)
>            for (i <- 1 to 3)
>                y = y*y
>            println("final y="+y)
>        }
>    }
>    def suspendableThree:Int @suspendable = {
>        shift { k:((Int)=>Unit) => k(3) }
>    }
>
>    def main(args:Array[String]) = test
> }
>
> --
> Jim




--
   __~O
  -\ <,
(*)/ (*)

reality goes far beyond imagination


Luc Duponcheel
Joined: 2008-12-19,
User offline. Last seen 34 weeks 3 days ago.
Re: variable scoping problem with continuations
indeed,

but then you explicitely introduce a new variable y "in the right scope"
and simply do exactly the same as with x
(you use two variables now: y and y0)
I wanted to write a monadic program use only one variable

... of course this does the trick ...

So yes, if you can let the users of the API
"guess what is happening behind the scenes"
then everything is fine

[ imho things like this should be part of the API doc]

when working monadically the users of the API can/have to decide
themselves what to do

(again: I'm not sure which one of the two approaches is the best one:
the plugin is certainly a fantastic thing, but I like the explicit monadic
approach as well)


thanks for your remark

Luc

On Mon, Apr 18, 2011 at 10:01 AM, Tiark Rompf <tiark.rompf@epfl.ch> wrote:
On Apr 17, 2011, at 6:33 PM, Luc Duponcheel wrote:
... interesting ...

it is nearly impossible to try to transalate
this program to a monadic one because of the
usage of vars

Why? This is (more or less) the result of the actual translation:
reify(suspendableThree).map { y0 => var y = y0 println("initial y="+y) for (i <- 1 to 3)
y = y*y
println("final y="+y) }
- Tiark


... whether encouraging using vars is a good thing is another discussion ...

 def jimMcBeathTest1() {
  import Int_Int_ControlTransformedIdentityMonadObject._
  resetC {
   // ok: this is possible
   var x = 3
   println("initial x = " + x)
   for (i <- 1 to 3) {
    x = x * x
   }
   println("final x = " + x)
   suspendableThree >= { (y: Int) =>
    println("initial y = " + y)
    // ko: no way to change something here
    for (i <- 1 to 3) {
     /* y = y * y */
    }
    println("final y = " + y)
    _return(y)
   }
  }
  def suspendableThree: M[Int] =
   shiftCC { c =>
    c(3)
   }
 }
 def jimMcBeathTest2() {
  import Int_Int_ControlTransformedIdentityMonadObject._
  resetC {
   // ok: this is possible
   var x = 3
   println("initial x = " + x)
   for (i <- 1 to 3) {
    x = x * x
   }
   println("final x = " + x)
   var my = suspendableThree
   // ko: not binding my to anything here
   println("initial y =")
   for { y <- my } yield { println(" " + y) }
   for { y <- my } yield { my = _return(y * y) }
   print("final y =")
   for { y <- my } yield { println(" " + y) }
   my
  }
  def suspendableThree: M[Int] =
   shiftCC { c =>
    c(3)
   }
 }

$ scala com.imaginej.apps.UsingControlMonads
initial x = 3
final x = 6561
initial y = 3
final y = 3
-------
initial x = 3
final x = 6561
initial y =



On Sun, Apr 17, 2011 at 2:14 AM, Tiark Rompf <tiark.rompf@epfl.ch> wrote:
Hey Jim, this looks like a bug. I think it has to do with y being transformed into a Ref object because it is modified from inside the closure that is passed to foreach. Please file a ticket.
- Tiark

On Apr 15, 2011, at 6:27 PM, Jim McBeath wrote:

> If you load the below test into the REPL (either 2.8.1 or 2.9.0.RC1;
> use "scala -P:continuations:enable") and evaluate Test.test, it gives
> this output:
>
> initial x=3
> final x=6561
> initial y=3
> final y=3
>
> The final y value should be 6561 rather than 3.
>
> The same happens if you compile it and run
> "scala -P:continuations:enable Test" from the command line.
>
> The only difference between x and y is that the initial assignment to y
> is done by a call to a suspendable method.  If you add a print statement
> inside the for loop, it appears to behave correctly while in the loop,
> with the value of y stepping up to 9, 81 and 6561, but that updated
> value gets lost when the loop exits.  If the call to suspendableThree
> is assigned to another variable such as z, and then y is set to the
> value of z, then the final y value is correct.
>
> Is this a bug, or am I doing something wrong with continuations?
>
> object Test {
>    import scala.util.continuations._
>    def test {
>        reset {
>            var x = 3
>            println("initial x="+x)
>            for (i <- 1 to 3)
>                x = x*x
>            println("final x="+x)
>
>            var y = suspendableThree
>            println("initial y="+y)
>            for (i <- 1 to 3)
>                y = y*y
>            println("final y="+y)
>        }
>    }
>    def suspendableThree:Int @suspendable = {
>        shift { k:((Int)=>Unit) => k(3) }
>    }
>
>    def main(args:Array[String]) = test
> }
>
> --
> Jim




--
   __~O
  -\ <,
(*)/ (*)

reality goes far beyond imagination





--
   __~O
  -\ <,
(*)/ (*)

reality goes far beyond imagination

Jim McBeath
Joined: 2009-01-02,
User offline. Last seen 42 years 45 weeks ago.
Re: variable scoping problem with continuations

Ticket #4493 created.

--
Jim

On Sun, Apr 17, 2011 at 02:14:07AM +0200, Tiark Rompf wrote:
> Date: Sun, 17 Apr 2011 02:14:07 +0200
> From: Tiark Rompf
> To: scala-language@googlegroups.com
> Subject: Re: [scala-language] variable scoping problem with continuations
>
> Hey Jim, this looks like a bug. I think it has to do with y being transformed into a Ref object because it is modified from inside the closure that is passed to foreach. Please file a ticket.
> - Tiark
>
> On Apr 15, 2011, at 6:27 PM, Jim McBeath wrote:
>
> > If you load the below test into the REPL (either 2.8.1 or 2.9.0.RC1;
> > use "scala -P:continuations:enable") and evaluate Test.test, it gives
> > this output:
> >
> > initial x=3
> > final x=6561
> > initial y=3
> > final y=3
> >
> > The final y value should be 6561 rather than 3.
> >
> > The same happens if you compile it and run
> > "scala -P:continuations:enable Test" from the command line.
> >
> > The only difference between x and y is that the initial assignment to y
> > is done by a call to a suspendable method. If you add a print statement
> > inside the for loop, it appears to behave correctly while in the loop,
> > with the value of y stepping up to 9, 81 and 6561, but that updated
> > value gets lost when the loop exits. If the call to suspendableThree
> > is assigned to another variable such as z, and then y is set to the
> > value of z, then the final y value is correct.
> >
> > Is this a bug, or am I doing something wrong with continuations?
> >
> > object Test {
> > import scala.util.continuations._
> > def test {
> > reset {
> > var x = 3
> > println("initial x="+x)
> > for (i <- 1 to 3)
> > x = x*x
> > println("final x="+x)
> >
> > var y = suspendableThree
> > println("initial y="+y)
> > for (i <- 1 to 3)
> > y = y*y
> > println("final y="+y)
> > }
> > }
> > def suspendableThree:Int @suspendable = {
> > shift { k:((Int)=>Unit) => k(3) }
> > }
> >
> > def main(args:Array[String]) = test
> > }
> >
> > --
> > Jim
>

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland