【问题标题】:Creating a Stream out of a couple of elements lazily in Scala在 Scala 中懒惰地用几个元素创建一个 Stream
【发布时间】:2018-09-17 08:08:24
【问题描述】:

出于测试目的,我想懒惰地计算 2 个元素:

  Stream(
    { Thread.sleep(2000); 1 },
    { Thread.sleep(2000); 2 },
    Stream.empty[Int]
  ).foreach(println)

但运行此代码不会产生预期的结果。这些值似乎同时出现在输出中。原因是Stream() 构造函数采用了一个必须急切计算的数组。因此,为了解决这个问题,我不得不像这样手动创建流的 thunk:

  (
    { Thread.sleep(2000); 1 } #::
    { Thread.sleep(2000); 2 } #::
    Stream.empty[Int]
  ).foreach(println)

现在完全按照预期工作,但不是特别漂亮。

有没有一种更简洁、更方便的方法来获得与Stream(a, b, c) 语法相似但懒惰地评估参数的东西?

谢谢

【问题讨论】:

  • 它可能应该句法相似但“语义上等效”,因为这正是你的不同语义在后面。

标签: scala lazy-evaluation scala-streams


【解决方案1】:

如果您创建一个特殊类,该类可以保存产生A 的按名称块以及有助于实例化此类的简短辅助方法:

class ByNameArg[+A](a: => A) {
  def unpack: A = a
}

/** Single lazy by-name argument wrapper */
def l[A](a: => A) = new ByNameArg(a)

那么你可以定义如下工厂方法:

def lazyStreamInit[A](xs: ByNameArg[A]*): Stream[A] = {
  if (xs.isEmpty) {
    Stream.empty[A]
  } else {
    xs.head.unpack #:: lazyStreamInit(xs.tail: _*)
  }
}

它可以在语法开销很小的情况下使用(您只需在 vararg-list 中传递的每个块前添加一个字符 l):

lazyStreamInit(
  l{ Thread.sleep(2000); 1 },
  l{ Thread.sleep(2000); 2 }
)

与通常的() => A-workaround 相比,这直接产生Stream[A],而不是Stream[() => A]

摆脱l{ () => ... } 似乎是不可能的,因为repeated by-name arguments are not supported


编辑

“通常的() => A-workaround”是指类似

Stream(
  { () => Thread.sleep(2000); 1 },
  { () => Thread.sleep(2000); 2 }
).map{ _() }.foreach(println)

请注意,您必须附加一个额外的map-step 才能使其成为Stream[A]

【讨论】:

    【解决方案2】:

    这将需要当前不支持的重复的按名称参数(http://docs.scala-lang.org/sips/repeated-byname.htmlhttps://github.com/scala/bug/issues/5787)。不过,它们可以通过in Dotty 获得。

    可以重复使用() => A,但是你需要写

    def makeStream[A](xs: (() => A)*) = ...
    
    makeStream(
      { () => Thread.sleep(2000); 1 },
      { () => Thread.sleep(2000); 2 }
    ).foreach(println)
    

    【讨论】:

    • 打印Main$$anon$1$$Lambda$132/1785210046@368239c8 Main$$anon$1$$Lambda$133/1552787810@9e89d68。你可能想map{_()}
    • 糟糕。我的意思是定义一个函数makeStream 来接受它们,而不是使用Stream.apply
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-08
    • 2010-11-11
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    • 1970-01-01
    相关资源
    最近更新 更多