【问题标题】:Most elegant repeat loop in ScalaScala 中最优雅的重复循环
【发布时间】:2011-04-23 11:59:22
【问题描述】:

我正在寻找类似的:

for(_ <- 1 to n)
  some.code()

那将是最短和最优雅的。 Scala 中没有类似的东西吗?

rep(n)
  some.code()

毕竟这是最常见的结构之一。

PS

我知道实现 rep 很容易,但我正在寻找预定义的东西。

【问题讨论】:

  • 基本上,您正在寻找 Ruby 的/Smalltalk 的 42.times do some_thing end 的等价物,对吧?我的意思是“等效”,不仅在功能意义上,而且在语法上的“轻量级”。
  • 优雅是一个主观标准。

标签: scala loops coding-style


【解决方案1】:
1 to n foreach { _ => some.code() }

【讨论】:

  • 与问题中提到的方式相比,这有什么优势(性能、风格)吗?
  • @benroth 没有。事实上,for (_ &lt;- 1 to n) some.code() 在编译过程中被翻译1 to n foreach { _ =&gt; some.code() }
  • 我不相信那是优雅的。 1 到 n 构造函数在调用 foreach 之前不会创建序列吗?如果 n = 65000,内存开销是多少?
  • @Willem 它创建了一个序列,类型为RangeRange 具有恒定的内存大小,与开始和结束无关。它存在性能问题,但比这更微妙。
【解决方案2】:

你可以创建一个辅助方法

def rep[A](n: Int)(f: => A) { if (n > 0) { f; rep(n-1)(f) } }

并使用它:

rep(5) { println("hi") }

根据@Jörgs 的评论,我写了这样一个时代方法:

class Rep(n: Int) {
  def times[A](f: => A) { loop(f, n) }
  private def loop[A](f: => A, n: Int) { if (n > 0) { f; loop(f, n-1) } }
}
implicit def int2Rep(i: Int): Rep = new Rep(i)

// use it with
10.times { println("hi") }

基于@DanGordon cmets,我写了这样一个time-method:

implicit class Rep(n: Int) {
    def times[A](f: => A) { 1 to n foreach(_ => f) } 
}

// use it with
10.times { println("hi") }

【讨论】:

  • n 很大时会发生堆栈溢出。就像这个网站的名字一样:)
  • 它可能是编译器优化的尾递归。但我不会在现实世界的编程中依赖它(例如,有一天我可能想要在尾部记录)。
  • 您可以通过使用 implicit 关键字声明类来简化此操作。事实上,您甚至不需要显式隐式转换,或 Rep 类中的第一个方法。
【解决方案3】:

我会建议这样的事情:

List.fill(10)(println("hi"))

还有其他方法,例如:

(1 to 10).foreach(_ => println("hi"))

感谢 Daniel S. 的更正。

【讨论】:

    【解决方案4】:

    使用 scalaz 6:

    scala> import scalaz._; import Scalaz._; import effects._;
    import scalaz._
    import Scalaz._
    import effects._
    
    scala> 5 times "foo"
    res0: java.lang.String = foofoofoofoofoo
    
    scala> 5 times List(1,2)
    res1: List[Int] = List(1, 2, 1, 2, 1, 2, 1, 2, 1, 2)
    
    scala> 5 times 10
    res2: Int = 50
    
    scala> 5 times ((x: Int) => x + 1).endo
    res3: scalaz.Endo[Int] = <function1>
    
    scala> res3(10)
    res4: Int = 15
    
    scala> 5 times putStrLn("Hello, World!")
    res5: scalaz.effects.IO[Unit] = scalaz.effects.IO$$anon$2@36659c23
    
    scala> res5.unsafePerformIO
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    

    [从here.复制的片段]

    【讨论】:

    • times in-fix 怎么样?这是高级黑客吗?
    猜你喜欢
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多