Scala等价于Python生成器?
是否可以在Scala中实现与PythonScala等价于Python生成器?,python,scala,Python,Scala,是否可以在Scala中实现与Pythonyield语句等价的东西,在该语句中,它记住使用它的函数的本地状态,并在每次调用它时“生成”下一个值 我想用这样的方法将递归函数转换成迭代器。有点像这样: # this is python def foo(i): yield i if i > 0: for j in foo(i - 1): yield j for i in foo(5): print i 除了,foo可能更复杂,并且通过一些非循环对象图递归 附加编
yield
语句等价的东西,在该语句中,它记住使用它的函数的本地状态,并在每次调用它时“生成”下一个值
我想用这样的方法将递归函数转换成迭代器。有点像这样:
# this is python
def foo(i):
yield i
if i > 0:
for j in foo(i - 1):
yield j
for i in foo(5):
print i
除了,foo
可能更复杂,并且通过一些非循环对象图递归
附加编辑:
让我添加一个更复杂的示例(但仍然很简单):
我可以编写一个简单的递归函数,在运行过程中打印内容:
// this is Scala
def printClass(clazz:Class[_], indent:String=""): Unit = {
clazz match {
case null =>
case _ =>
println(indent + clazz)
printClass(clazz.getSuperclass, indent + " ")
for (c <- clazz.getInterfaces) {
printClass(c, indent + " ")
}
}
}
//这是Scala
def printClass(clazz:Class[zz;],indent:String=“”):单位={
克拉兹比赛{
大小写null=>
案例=>
println(缩进+重叠)
printClass(clazz.getSuperclass,缩进+“”)
对于(c)
案例=>
苏多兹
为了(c以一般方式进行此操作,我认为您需要
简单的实现(徒手,未编译/检查):
发生的情况是,对shift
的任何调用都会捕获从调用它的位置到调用它的reset
块末尾的控制流。这将作为k
参数传递到shift函数中
因此,在上面的示例中,每个giveItUp(x)
返回x
(到该点为止)的值,并将剩余的计算保存在state
变量中。它由hasNext
和next
方法从外部驱动
轻点说,这显然是一种糟糕的实现方式。但我最好在深夜不用编译器的情况下完成这项工作。虽然Python生成器很酷,但在Scala中尝试复制它们并不是最好的方式。例如,以下代码的作用与您想要的相同:
def classStream(clazz:Class[\u]]:Stream[Class[\u]]=clazz匹配{
case null=>Stream.empty
案例=>(
克拉兹
#::类流(clazz.getSuperclass)
#::clazz.getInterfaces.toStream.flatMap(classStream)
#::Stream.empty
)
}
在其中,流是惰性生成的,因此在请求之前不会处理任何元素,您可以通过运行以下命令进行验证:
def classStream(clazz:Class[\u]]:Stream[Class[\u]]=clazz匹配{
case null=>Stream.empty
案例=>(
克拉兹
#:{println(clazz.toString+“:super”);类流(clazz.getSuperclass)}
#:{println(clazz.toString+“:interfaces”);clazz.getInterfaces.toStream.flatMap(classStream)}
#::Stream.empty
)
}
只需在生成的流
上调用.Iterator
,即可将结果转换为迭代器
:
def classIterator(clazz: Class[_]): Iterator[Class[_]] = classStream(clazz).iterator
使用Stream
的foo
定义将呈现如下:
scala>def foo(i:Int):Stream[Int]=i#::(if(i>0)foo(i-1)else Stream.empty)
foo:(i:Int)流[Int]
scala>foo(5)foreach println
5.
4.
3.
2.
1.
0
另一种替代方法是连接各种迭代器,注意不要预先计算它们。下面是一个示例,还包含调试消息以帮助跟踪执行:
def yieldClass(clazz: Class[_]): Iterator[Class[_]] = clazz match {
case null => println("empty"); Iterator.empty
case _ =>
def thisIterator = { println("self of "+clazz); Iterator(clazz) }
def superIterator = { println("super of "+clazz); yieldClass(clazz.getSuperclass) }
def interfacesIterator = { println("interfaces of "+clazz); clazz.getInterfaces.iterator flatMap yieldClass }
thisIterator ++ superIterator ++ interfacesIterator
}
这与您的代码非常接近。我没有使用sudoYield
,而是使用定义,然后按照我的意愿将它们连接起来
因此,虽然这不是一个答案,但我认为你在这里找错了方向。试图用Scala编写Python肯定是徒劳无益的。更努力地使用Scala习惯用法来实现同样的目标。另一个基于continuations插件的解决方案,这次使用了或多或少封装的生成器类型
import scala.continuations._
import scala.continuations.ControlContext._
object Test {
def loopWhile(cond: =>Boolean)(body: =>(Unit @suspendable)): Unit @suspendable = {
if (cond) {
body
loopWhile(cond)(body)
} else ()
}
abstract class Generator[T] {
var producerCont : (Unit => Unit) = null
var consumerCont : (T => Unit) = null
protected def body : Unit @suspendable
reset {
body
}
def generate(t : T) : Unit @suspendable =
shift {
(k : Unit => Unit) => {
producerCont = k
if (consumerCont != null)
consumerCont(t)
}
}
def next : T @suspendable =
shift {
(k : T => Unit) => {
consumerCont = k
if (producerCont != null)
producerCont()
}
}
}
def main(args: Array[String]) {
val g = new Generator[Int] {
def body = {
var i = 0
loopWhile(i < 10) {
generate(i)
i += 1
}
}
}
reset {
loopWhile(true) {
println("Generated: "+g.next)
}
}
}
}
导入scala.continuations_
导入scala.continuations.ControlContext_
对象测试{
def loopWhile(cond:=>Boolean)(body:=>(Unit@suspendable)):Unit@suspendable={
如果(秒){
身体
循环时间(秒)(主体)
}else()
}
抽象类生成器[T]{
var producerCont:(单位=>单位)=null
var consumerCont:(T=>Unit)=null
受保护的def主体:单元@suspendable
重置{
身体
}
def生成(t:t):单位@suspendable=
移位{
(k:单位=>单位=>{
producerCont=k
if(consumerCont!=null)
消费者通讯(t)
}
}
def next:T@suspendable=
移位{
(k:T=>单位)=>{
consumerCont=k
如果(producerCont!=null)
producerCont()
}
}
}
def main(参数:数组[字符串]){
val g=新发电机[Int]{
def正文={
变量i=0
loopWhile(i<10){
生成(i)
i+=1
}
}
}
重置{
loopWhile(真){
println(“生成:+g.next”)
}
}
}
}
Scala的for循环的形式for(e是您正在寻找的
假设您想要创建一个随机数生成器。生成的数字应该存储在一个延迟计算的无限流中,该流可以借助我们内置的特定于域的关键字Yield
来构建
import com.thoughtworks.dsl.keys.Yield
def xorshiftRandomGenerator(seed: Int): Stream[Int] = {
val tmp1 = seed ^ (seed << 13)
val tmp2 = tmp1 ^ (tmp1 >>> 17)
val tmp3 = tmp2 ^ (tmp2 << 5)
!Yield(tmp3)
xorshiftRandomGenerator(tmp3)
}
import com.thoughtworks.dsl.keys.Yield
def xorshift随机生成器(种子:Int):流[Int]={
val tmp1=seed^(seed>>17)
val tmp3=tmp2^(tmp2很难想出一个通过标准技术无法实现的简单示例。例如,我认为您的yieldClass
示例可以通过使用迭代器来实现。++
很聪明。但是,是的,我认为yieldClass
可以通过移位/重置来实现。我不知道什么时候它将不需要插件就可以进入编译器。我认为大多数复杂性都可以分解成一个“生成器库”.我认为Rich Dougherty的博客是这些生物最好的解释来源。关于迭代器,你是对的。++.works。我必须检查Rich的博客。这是一个副本,但奇怪的是,我没有看到原件
import scala.continuations._
import scala.continuations.ControlContext._
object Test {
def loopWhile(cond: =>Boolean)(body: =>(Unit @suspendable)): Unit @suspendable = {
if (cond) {
body
loopWhile(cond)(body)
} else ()
}
abstract class Generator[T] {
var producerCont : (Unit => Unit) = null
var consumerCont : (T => Unit) = null
protected def body : Unit @suspendable
reset {
body
}
def generate(t : T) : Unit @suspendable =
shift {
(k : Unit => Unit) => {
producerCont = k
if (consumerCont != null)
consumerCont(t)
}
}
def next : T @suspendable =
shift {
(k : T => Unit) => {
consumerCont = k
if (producerCont != null)
producerCont()
}
}
}
def main(args: Array[String]) {
val g = new Generator[Int] {
def body = {
var i = 0
loopWhile(i < 10) {
generate(i)
i += 1
}
}
}
reset {
loopWhile(true) {
println("Generated: "+g.next)
}
}
}
}
case class Countdown(start: Int) extends Traversable[Int] {
def foreach[U](f: Int => U) {
var j = start
while (j >= 0) {f(j); j -= 1}
}
}
for (i <- Countdown(5)) println(i)
// or equivalent:
Countdown(5) foreach println
// v1 (without indentation)
case class ClassStructure(c: Class[_]) {
def foreach[U](f: Class[_] => U) {
if (c eq null) return
f(c)
ClassStructure(c.getSuperclass) foreach f
c.getInterfaces foreach (ClassStructure(_) foreach f)
}
}
for (c <- ClassStructure(<foo/>.getClass)) println(c)
// or equivalent:
ClassStructure(<foo/>.getClass) foreach println
// v2 (with indentation)
case class ClassWithIndent(c: Class[_], indent: String = "") {
override def toString = indent + c
}
implicit def Class2WithIndent(c: Class[_]) = ClassWithIndent(c)
case class ClassStructure(cwi: ClassWithIndent) {
def foreach[U](f: ClassWithIndent => U) {
if (cwi.c eq null) return
f(cwi)
ClassStructure(ClassWithIndent(cwi.c.getSuperclass, cwi.indent + " ")) foreach f
cwi.c.getInterfaces foreach (i => ClassStructure(ClassWithIndent(i, cwi.indent + " ")) foreach f)
}
}
for (c <- ClassStructure(<foo/>.getClass)) println(c)
// or equivalent:
ClassStructure(<foo/>.getClass) foreach println
class scala.xml.Elem
class scala.xml.Node
class scala.xml.NodeSeq
class java.lang.Object
interface scala.collection.immutable.Seq
interface scala.collection.immutable.Iterable
interface scala.collection.immutable.Traversable
interface scala.collection.Traversable
interface scala.collection.TraversableLike
interface scala.collection.generic.HasNewBuilder
interface scala.collection.generic.FilterMonadic
interface scala.collection.TraversableOnce
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.generic.GenericTraversableTemplate
interface scala.collection.generic.HasNewBuilder
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.generic.GenericTraversableTemplate
interface scala.collection.generic.HasNewBuilder
interface scala.ScalaObject
interface scala.collection.TraversableLike
interface scala.collection.generic.HasNewBuilder
interface scala.collection.generic.FilterMonadic
interface scala.collection.TraversableOnce
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.Immutable
interface scala.ScalaObject
interface scala.collection.Iterable
interface scala.collection.Traversable
interface scala.collection.TraversableLike
interface scala.collection.generic.HasNewBuilder
interface scala.collection.generic.FilterMonadic
interface scala.collection.TraversableOnce
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.generic.GenericTraversableTemplate
interface scala.collection.generic.HasNewBuilder
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.generic.GenericTraversableTemplate
interface scala.collection.generic.HasNewBuilder
interface scala.ScalaObject
interface scala.collection.IterableLike
interface scala.Equals
interface scala.collection.TraversableLike
interface scala.collection.generic.HasNewBuilder
interface scala.collection.generic.FilterMonadic
interface scala.collection.TraversableOnce
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.generic.GenericTraversableTemplate
interface scala.collection.generic.HasNewBuilder
interface scala.ScalaObject
interface scala.collection.IterableLike
interface scala.Equals
interface scala.collection.TraversableLike
interface scala.collection.generic.HasNewBuilder
interface scala.collection.generic.FilterMonadic
interface scala.collection.TraversableOnce
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.Seq
interface scala.PartialFunction
interface scala.Function1
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.Iterable
interface scala.collection.Traversable
interface scala.collection.TraversableLike
interface scala.collection.generic.HasNewBuilder
interface scala.collection.generic.FilterMonadic
interface scala.collection.TraversableOnce
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.generic.GenericTraversableTemplate
interface scala.collection.generic.HasNewBuilder
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.generic.GenericTraversableTemplate
interface scala.collection.generic.HasNewBuilder
interface scala.ScalaObject
interface scala.collection.IterableLike
interface scala.Equals
interface scala.collection.TraversableLike
interface scala.collection.generic.HasNewBuilder
interface scala.collection.generic.FilterMonadic
interface scala.collection.TraversableOnce
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.generic.GenericTraversableTemplate
interface scala.collection.generic.HasNewBuilder
interface scala.ScalaObject
interface scala.collection.SeqLike
interface scala.collection.IterableLike
interface scala.Equals
interface scala.collection.TraversableLike
interface scala.collection.generic.HasNewBuilder
interface scala.collection.generic.FilterMonadic
interface scala.collection.TraversableOnce
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.generic.GenericTraversableTemplate
interface scala.collection.generic.HasNewBuilder
interface scala.ScalaObject
interface scala.collection.SeqLike
interface scala.collection.IterableLike
interface scala.Equals
interface scala.collection.TraversableLike
interface scala.collection.generic.HasNewBuilder
interface scala.collection.generic.FilterMonadic
interface scala.collection.TraversableOnce
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.collection.SeqLike
interface scala.collection.IterableLike
interface scala.Equals
interface scala.collection.TraversableLike
interface scala.collection.generic.HasNewBuilder
interface scala.collection.generic.FilterMonadic
interface scala.collection.TraversableOnce
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.xml.Equality
interface scala.Equals
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface scala.ScalaObject
interface java.io.Serializable
import com.thoughtworks.dsl.keys.Yield
def xorshiftRandomGenerator(seed: Int): Stream[Int] = {
val tmp1 = seed ^ (seed << 13)
val tmp2 = tmp1 ^ (tmp1 >>> 17)
val tmp3 = tmp2 ^ (tmp2 << 5)
!Yield(tmp3)
xorshiftRandomGenerator(tmp3)
}