« Return to Thread: [scala] Simulating python yield with scala continuations
As a side note, I think the point with Python's generators is best given with tree traversal:
def inorder(t):
if t:
for x in inorder(t.left):
yield x
yield t.label
for x in inorder(t.right):
yield x
No explicit state management, no result building up. As soon as I have a value, I yield it.--
On Jun 18, 2009, at 6:56 AM, Arnold deVos wrote:
Well yes, you can always string together pieces with append, andThen and so on
but continuations are all about coding this sort of thing in direct-style.
The benefit is not so clear with a simple example like mine.
But the point of the post is not to motivate continuations. I am wanting
exchange knowledge with others that already do want to continuations and tease
out bugs in the implementation.
-- Arnold
On Thu, 18 Jun 2009 01:33:57 pm Jorge Ortiz wrote:
Scala has lazy collections, which, AFAIK, can do whatever generators can
without needing the continuations plugin.
val generate =
(
Array("first").projection append
(1 to 4).map(_.toString) append
Array("last").projection
).elements
for (r <- generate) println(r)
The code is, admittedly, a little ugly, but could be made a little cleaner
with 2.8 collections.
(Note this won't work in the interpreter, as the interpreter calls toString
on "generate", which forces its evaluation. If you suppress the call to
toString, it works as specified.)
--j
On Wed, Jun 17, 2009 at 7:17 PM, Arnold deVos <
adv-list-scala@...> wrote:
I'm interested in the upcoming continuations support so I thought I would
try
to build something similar to the python generators with it. Here is a
scrap
of python:
def generate():
yield "first"
for i in range(1,4):
yield str(i)
yield "last"
In python this function returns an iterator over the values passed to the
yield statements. The nice thing is: it is lazy and can be used as a
coroutine. Anyway, if we iterate like this:
for r in generate():
print r
It prints this:
first
1
2
3
last
Here is a scala version in which a produce() method serves the same role
as python's yield:
object Generator {
def generate = {
val g = new Generator[String]
reset {
g produce "first"
g produce 1.toString
g produce 2.toString
g produce 3.toString
g produce "last"
}
g
}
def main(args: Array[String]) {
for( a <- generate ) println(a)
}
}
This also prints
first
1
2
3
last
The Generator class is defined in terms of shift() as follows:
class Generator[A] extends Iterator[A] {
private var a: A = _
private var k: (Unit => Unit) = null
def next = {
val a0 = a
val k0 = k
k = null
k0()
a0
}
def hasNext = k != null
def produce(a0: A): Unit @ suspendable = {
a = a0
shift { k0: (Unit => Unit) => k = k0 }
}
}
But the example is not quite the same as the python because that had a
loop in
the generate function. Lets try that in the scala version, replacing the
generate method with:
def generate = {
val g = new Generator[String]
reset {
g produce "first"
for( i <- 1 to 4) { g produce i.toString }
g produce "last"
}
g
}
But this does not compile:
generator.scala:28: error: type mismatch;
found : (Int) => Unit @scala.continuations.cps[Unit,Unit]
required: (Int) => Unit
for( i <- 1 to 4) { g produce i.toString }
^
one error found
Substituting a while loop produces a different compile error. Do any
continuation experts/experimenters out there know what the problem is?
The example was compiled with scala r17271 plus the latest continuations
plugin from trunk as of r18035 for reasons explained in the previous
post. This may be the problem, I don't know.
- Arnold
__~O
-\ <, Christos KK Loverdos
(*)/ (*) http://ckkloverdos.com
« Return to Thread: [scala] Simulating python yield with scala continuations
| Free embeddable forum powered by Nabble | Forum Help |