我理解Ruby和Python的收益率.Scala的收益率是多少?
是否有可能在Scala中实现与Python 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
Run Code Online (Sandbox Code Playgroud)
除此之外,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 + " ")
}
}
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,我希望有一个库,允许我轻松更改一些语句并使其作为迭代器工作:
// this is not …Run Code Online (Sandbox Code Playgroud) 我是Scala的新手,据我所知,Scala中的收益与C#中的收益不同,它更像是选择.
Scala有类似于C#的收益吗?C#的收益很好,因为它使编写迭代器变得非常容易.
更新:这是来自C#的伪代码示例,我希望能够在Scala中实现:
public class Graph<T> {
public IEnumerable<T> BreadthFirstIterator() {
List<T> currentLevel = new List<T>();
currentLevel.add(_root);
while ( currentLevel.count > 0 ) {
List<T> nextLevel = new List<T>();
foreach( var node in currentLevel ) {
yield return node;
nextLevel.addRange( node.Children );
}
currentLevel = nextLevel;
}
}
}
Run Code Online (Sandbox Code Playgroud)
此代码实现了图的迭代广度优先遍历,使用yield,它返回一个迭代器,以便调用者可以使用常规for循环遍历图,例如:
graph.BreadthFirstIterator().foreach( n => Console.WriteLine( n ) );
Run Code Online (Sandbox Code Playgroud)
在C#中,yield只是语法糖,可以很容易地编写迭代器(IEnumerable<T>在.Net中,类似于IterableJava).作为迭代器,它的评估很懒散.
更新II:我可能在这里错了,但我认为C#中的整个收益点是你不必编写更高阶函数.例如,你可以编写一个常规for循环或使用像select/ map/ filter/ 这样的方法,where而不是传入一个函数,然后遍历序列.
如graph.iterator().foreach(n => println(n))代替graph.iterator( …
我正在为博士研究编写代码并开始使用Scala.我经常要做文字处理.我已经习惯了Python,其'yield'语句对于在大型(通常是不规则结构化的)文本文件上实现复杂的迭代器非常有用.类似的结构存在于其他语言(例如C#)中,这是有充分理由的.
是的我知道之前有过这样的线索.但它们看起来像是黑客攻击(或至少解释得很糟糕)的解决方案,这些解决方案并不能很好地运作并且通常具有不明确的局限性.我想编写这样的代码:
import generator._
def yield_values(file:String) = {
generate {
for (x <- Source.fromFile(file).getLines()) {
# Scala is already using the 'yield' keyword.
give("something")
for (field <- ":".r.split(x)) {
if (field contains "/") {
for (subfield <- "/".r.split(field)) { give(subfield) }
} else {
// Scala has no 'continue'. IMO that should be considered
// a bug in Scala.
// Preferred: if (field.startsWith("#")) continue
// Actual: Need to indent all following code
if (!field.startsWith("#")) {
val some_calculation = { ... …Run Code Online (Sandbox Code Playgroud) 基本上我想转换这个:
def data(block: T => Unit)
Run Code Online (Sandbox Code Playgroud)
到Stream(dataToStream是执行此转换的假设函数):
val dataStream: Stream[T] = dataToStream(data)
Run Code Online (Sandbox Code Playgroud)
我想这个问题可以通过延续来解决:
// let's assume that we don't know how data is implemented
// we just know that it generates integers
def data(block: Int => Unit) { for (i <- 0 to 10) block(i) }
// here we can print all data integers
data { i => println(i) }
// >> but what we really want is to convert data to the stream <<
// very dumb solution is …Run Code Online (Sandbox Code Playgroud) 我是Scala的新手,并试图绕过我试图重现yield returnC#语句的延续.
在这篇文章之后,我写了以下代码:
package com.company.scalatest
import scala.util.continuations._;
object GenTest {
val gen = new Generator[Int] {
def produce = {
yieldValue(1)
yieldValue(2)
yieldValue(3)
yieldValue(42)
}
}
// Does not compile :(
// val gen2 = new Generator[Int] {
// def produce = {
// var ints = List(1, 2, 3, 42);
//
// ints.foreach((theInt) => yieldValue(theInt));
// }
// }
// But this works?
val gen3 = new Generator[Int] {
def produce = {
var ints …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用各种Scala实现的C#类似的yield return(即这一个)和"for" - 这样的构造:
private def permutations[T](s: Vector[T]) = {
def swap(i: Int, j: Int) {
val tmp = s(i)
s.set(i, s.get(j))
s.set(j, tmp)
}
iterator[Vector[T]] {
def generate(left: Int, right: Int): Unit @cps[Iteration[Vector[T]]] = {
if (left >= right)
yieldValue(s)
else {
generate(left, right)
for (i <- left to right) {
swap(left, i)
generate(left+1, right)
swap(left, i)
}
}
}
generate(0, s.size-1)
}
}
Run Code Online (Sandbox Code Playgroud)
但是这段代码编译错误:
error: no type parameters for method foreach: (f: (Int) => U)Unit exist …Run Code Online (Sandbox Code Playgroud)