scala中的for循环没有序列?

发布于 2024-12-03 15:17:45 字数 533 浏览 4 评论 0原文

因此,在学习“Scala for the Impressive”时,我发现自己在想:是否可以在没有序列的情况下使用 Scala for 循环?

例如,书中有一个练习要求您构建一个不能递增超过 Integer.MAX_VALUE 的计数器对象。为了测试我的解决方案,我编写了以下代码:

var c = new Counter
for( i <- 0 to Integer.MAX_VALUE ) c.increment()

这会引发错误:序列不能包含超过 Int.MaxValue 元素。 在我看来,这意味着 Scala 首先使用值 0 到 Integer.MaxValue 分配和填充序列对象,然后对该序列对象执行 foreach 循环。

我意识到我可以这样做:

var c = new Counter
while(c.value < Integer.MAX_VALUE ) c.increment()

但是有没有办法用 for 语句执行传统的 C 风格的 for 循环?

So, while working my way through "Scala for the Impatient" I found myself wondering: Can you use a Scala for loop without a sequence?

For example, there is an exercise in the book that asks you to build a counter object that cannot be incremented past Integer.MAX_VALUE. In order to test my solution, I wrote the following code:

var c = new Counter
for( i <- 0 to Integer.MAX_VALUE ) c.increment()

This throws an error: sequences cannot contain more than Int.MaxValue elements.
It seems to me that means that Scala is first allocating and populating a sequence object, with the values 0 through Integer.MaxValue, and then doing a foreach loop on that sequence object.

I realize that I could do this instead:

var c = new Counter
while(c.value < Integer.MAX_VALUE ) c.increment()

But is there any way to do a traditional C-style for loop with the for statement?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

世俗缘 2024-12-10 15:17:45

事实上,0 到 N 实际上并没有用从 0N 的整数填充任何内容。相反,它创建一个 scala.collection.immutable.Range 实例,它将其方法应用于动态生成的所有整数。

您遇到的错误只是因为您必须能够将元素数量(无论它们是否实际存在)放入 Int 的正数部分,以便维护 Int 的契约代码>长度方法。 1 到 Int.MaxValue 工作正常,0 到 Int.MaxValue 也可以正常工作。后者就是 while 循环正在执行的操作(to 包含正确的端点,until 省略它)。

无论如何,由于 Scala for 与 C for 是一个非常不同(更通用)的生物,简短的答案是否定的,你不能做完全相同的事情。但是您可能可以使用 for 做您想做的事情(尽管可能没有您想要的那么快,因为存在一些性能损失)。

In fact, 0 to N does not actually populate anything with integers from 0 to N. It instead creates an instance of scala.collection.immutable.Range, which applies its methods to all the integers generated on the fly.

The error you ran into is only because you have to be able to fit the number of elements (whether they actually exist or not) into the positive part of an Int in order to maintain the contract for the length method. 1 to Int.MaxValue works fine, as does 0 until Int.MaxValue. And the latter is what your while loop is doing anyway (to includes the right endpoint, until omits it).

Anyway, since the Scala for is a very different (much more generic) creature than the C for, the short answer is no, you can't do exactly the same thing. But you can probably do what you want with for (though maybe not as fast as you want, since there is some performance penalty).

歌枕肩 2024-12-10 15:17:45

哇,对于一个简单的问题有一些很好的技术答案(这很好!)但如果有人只是在寻找一个简单的答案:

//start from 0, stop at 9 inclusive
for (i <- 0 until 10){
    println("Hi " + i)
}

//or start from 0, stop at 9 inclusive
for (i <- 0 to 9){
    println("Hi " + i)
}

正如雷克斯指出的那样,“to”包括正确的端点,“until”省略它。

Wow, some nice technical answers for a simple question (which is good!) But in case anyone is just looking for a simple answer:

//start from 0, stop at 9 inclusive
for (i <- 0 until 10){
    println("Hi " + i)
}

//or start from 0, stop at 9 inclusive
for (i <- 0 to 9){
    println("Hi " + i)
}

As Rex pointed out, "to" includes the right endpoint, "until" omits it.

离笑几人歌 2024-12-10 15:17:45

是或否,这取决于您的要求。如果您询问是否可以迭代整数序列而不必先构建该序列,那么可以,例如使用流:

def fromTo(from : Int, to : Int) : Stream[Int] = 
  if(from > to) {
    Stream.empty
  } else {
    // println("one more.") // uncomment to see when it is called
    Stream.cons(from, fromTo(from + 1, to))
  }

然后:

for(i <- fromTo(0, 5)) println(i)

通过定义 hasNext 和 next 编写您自己的迭代器是另一种选择。

如果您询问是否可以使用“for”语法来编写“本机”循环,即通过递增某些本机整数而不是迭代对象实例生成的值来工作的循环,那么答案是,据我所知,没有。正如您可能知道的,“for”推导式是对 flatMap、filter、map 和/或 foreach 的调用组合的语法糖(所有这些都在 FilterMonadic 特征),取决于生成器的嵌套及其类型。您可以尝试编译一些循环并打印其编译器中间表示,

scalac -Xprint:refchecks

以查看它们是如何扩展的。

Yes and no, it depends what you are asking for. If you're asking whether you can iterate over a sequence of integers without having to build that sequence first, then yes you can, for instance using streams:

def fromTo(from : Int, to : Int) : Stream[Int] = 
  if(from > to) {
    Stream.empty
  } else {
    // println("one more.") // uncomment to see when it is called
    Stream.cons(from, fromTo(from + 1, to))
  }

Then:

for(i <- fromTo(0, 5)) println(i)

Writing your own iterator by defining hasNext and next is another option.

If you're asking whether you can use the 'for' syntax to write a "native" loop, i.e. a loop that works by incrementing some native integer rather than iterating over values produced by an instance of an object, then the answer is, as far as I know, no. As you may know, 'for' comprehensions are syntactic sugar for a combination of calls to flatMap, filter, map and/or foreach (all defined in the FilterMonadic trait), depending on the nesting of generators and their types. You can try to compile some loop and print its compiler intermediate representation with

scalac -Xprint:refchecks

to see how they are expanded.

本王不退位尔等都是臣 2024-12-10 15:17:45

那里有很多这样的东西,但我现在懒得去谷歌搜索它们。以下是非常规范的:

@scala.annotation.tailrec
def loop(from: Int, until: Int)(f: Int => Unit): Unit = {
  if (from < until) {
    f(from)
    loop(from + 1, until)(f)
  }
}

loop(0, 10) { i =>
  println("Hi " + i)
}

There's a bunch of these out there, but I can't be bothered googling them at the moment. The following is pretty canonical:

@scala.annotation.tailrec
def loop(from: Int, until: Int)(f: Int => Unit): Unit = {
  if (from < until) {
    f(from)
    loop(from + 1, until)(f)
  }
}

loop(0, 10) { i =>
  println("Hi " + i)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文