Scala是否具有与C#收益等价的功能?
我是Scala的新手,从我的理解来看,Scala中的收益不像C#中的收益率,它更像是select。
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;
}
}
}
这段代码实现了对图的迭代宽度优先遍历,使用yield,它返回一个迭代器,以便调用者可以使用常规for循环遍历图,例如:
graph.BreadthFirstIterator().foreach( n => Console.WriteLine( n ) );
在C#中,yield只是语法糖,可以很容易地编写迭代器(.net中的IEnumerable<T>
,类似于Java中的Iterable
)。 作为一个迭代器,懒惰地评估它。
更新II:我可能在这里是错误的,但我认为C#中的整体收益点是这样的,你不必编写更高阶的函数。 例如,您可以编写循环的常规或使用像select
/ map
/ filter
/这样的方法where
而不是传入将会遍历序列的函数。
例如graph.iterator().foreach(n => println(n))
而不是graph.iterator( n => println(n))
。
这样你可以轻松地链接它们,例如graph.iterator().map(x => x.foo).filter(y => y.bar >= 2).foreach(z => println(z))
。
劫持这个单词产量在这里与通常的意图是分开的:作为协同程序中的入口/出口标记。 以上示例中的C# BreadthFirstIterator
似乎在其协程意义上使用yield
; 值由返回后yield
,以激活下一个电话BreadthFirstIterator
的IEnumerable
将继续后面的语句yield
。
在C#中, yield
与迭代的思想相结合,而不是一个更一般的控制流程语句,但在有限的领域内,它的行为就是协同程序的行为。 Scala的定界延续可能允许我们定义协程。 在此之前,斯卡拉缺乏这样的能力,尤其是考虑到其yield
替代含义。
是的,你可能想看看这个问题的答案:什么是斯卡拉的收益?
以下是来自Scala的这种类型构造的文档:http://www.scala-lang.org/node/111
更新:
本博客讨论C#产量和Scala:http://hestia.typepad.com/flatlander/2009/01/scala-for-c-programmers-part-1-mixins-and-traits.html
他详细说明了扩展如何用于使IENumerable与使用Scala中的Traits相比的工作。
所以,你是正确的,yield在Scala中的功能与C#不一样,但这是因为它们有很大的不同,所以如果你想将这个BreadthFirst作为一个特性来做,那么你可以调用map()
和filter
和foreach
方法一样,就像在C#中一样,但特性将有助于解决如何遍历集合的问题。
我认为答案(禁止2.8中的变化)是答案是否定的,Scala没有类似于C#编写迭代器的语法糖(IEumerable或Iterable的实现)。
但是,在Scala中,您可以通过向遍历中的每个项目调用的遍历函数传递一个相似的结果。 这种方法也可以在C#中以相同的方式实现。
下面是我如何在C#中编写Traverse而不使用yield:
public class Graph<T> {
public void BreadthFirstTraversal( Action<T> f) {
List<T> currentLevel = new List<T>();
currentLevel.add(_root);
while ( currentLevel.count > 0 ) {
List<T> nextLevel = new List<T>();
foreach( var node in currentLevel ) {
f(node);
nextLevel.addRange( node.Children );
}
currentLevel = nextLevel;
}
}
}
你可以像这样使用它:
graph.BreadthFirstTraversal( n => Console.WriteLine( n ) );
或者像这样:
graph.BreadthFirstTraversal( n =>
{
Console.WriteLine(n);
DoSomeOtherStuff(n);
});
链接地址: http://www.djcxy.com/p/54331.html