XTend循环支持和添加范围支持

10

我似乎找不到一种很好的方法在Xtend中表达以下内容,而不使用while循环:

for(int i = 0; i < 3; i++){
    println("row ");
}
println("your boat");

所以,我想我的问题有两个部分:

  • 有没有更好的方法来完成上面的任务?在他们的文档中我没有看到任何有前途的内容。
  • 该语言具有的大部分功能都是Xtend库扩展(它们很棒!)。是否有类似于Python的range()功能,我不知道吗?

最后,我自己编写了一些代码,得到了类似以下的结果:

class LanguageUtil {

def static Iterable<Integer> range(int stop) {
    range(0, stop)
}

def static Iterable<Integer> range(int start, int stop) {
    new RangeIterable(start, stop, 1)
}

def static Iterable<Integer> range(int start, int stop, int step) {
    new RangeIterable(start, stop, step)
}
}

// implements Iterator and Iterable which is bad form.
class RangeIterable implements Iterator<Integer>, Iterable<Integer> {
val int start
val int stop
val int step
var int current

new(int start, int stop, int step) {
    this.start = start;
    this.stop = stop;
    this.step = step
    this.current = start
}

override hasNext() {
    current < stop
}

override next() {
    val ret = current
    current = current + step
    ret
}

override remove() {
    throw new UnsupportedOperationException("Auto-generated function stub")
}

/**
 * This is bad form. We could return a 
 * new RangeIterable here, but that seems worse.
 */
override iterator() {
    this
}
}
6个回答

18

确切的替代方案是什么?

for(int i = 0; i < 3; i++){
    println("row ");
}
is
for (i : 0 ..< 3) {
    println("row ")
}

注意这个排除结尾的范围运算符:..<


14

你也可以用更通俗易懂的方式来做到这一点

(1..3).forEach[println("row")]

我对Xtend还很陌生,但它让在jvm上编程变得非常棒。


请注意,您在lambda表达式[]内有一些限制。例如,如果您想在该表达式内访问局部变量localVar,则会收到“无法在lambda表达式内引用非最终变量localVar”的错误提示。我认为rzymek的答案更完整地回答了原帖提出的问题。 - CuongHuyTo
如果您还需要函数中的迭代索引,请参见我的回答 - Viliam Simko

5
对我而言,基于范围的forEach意味着该范围在某种程度上是有意义的。如果没有迭代变量循环特定次数,我发现Ruby的times循环更能清晰地表达意图:
3.times [|println("row")]

不幸的是,这不是IntegerExtensions的一部分,但实现很简单:

def static times(int iterations, Runnable runnable) {
    if (iterations < 0) throw new IllegalArgumentException(
            '''Can't iterate negative («iterations») times.''')
    for (i: 0 ..< iterations) runnable.run()
}

建议将此添加到核心Xtend库中 https://bugs.eclipse.org/bugs/show_bug.cgi?id=489944 - vorburger

4

嘿,我过了一会儿找到了答案:

for(i: 1..3) {
    println("row ")
}

你甚至可以避免编写 Integer,因为 Xtend 会自动推断。 - Viliam Simko

3

实际上,forEach()有一个版本可以接受带有两个参数的lambda表达式。如果需要在循环内访问迭代索引,则此函数非常有用。

(10..12).forEach[ x, i | println('''element=«x» index=«i»''')]

输出:

element=10 index=0
element=11 index=1
element=12 index=2

3
Xtend 2.6 开始,我们也支持“传统”的 for 循环,就像在 Java 中一样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接