- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
variable scoping problem with continuations
Fri, 2011-04-15, 17:27
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
Sun, 2011-04-17, 17:47
#2
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:
--
__~O
-\ <,
(*)/ (*)
reality goes far beyond imagination
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
Mon, 2011-04-18, 09:07
#3
Re: variable scoping problem with continuations
On Apr 17, 2011, at 6:33 PM, Luc Duponcheel wrote:
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
... 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
Mon, 2011-04-18, 09:27
#4
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:
--
__~O
-\ <,
(*)/ (*)
reality goes far beyond imagination
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
Mon, 2011-04-18, 16:47
#5
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
>
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