【问题标题】:Scala worksheet not working for this code , no compilation error shownScala 工作表不适用于此代码,未显示编译错误
【发布时间】:2017-10-07 05:17:48
【问题描述】:

我在 eclipse 的 scala 工作表中尝试了一些东西。这没有显示任何输出,也没有显示任何错误或警告。

object stream {
  println("Welcome to the Scala worksheet")

  def cons[T](hd: T, t1: => Stream[T]): Stream[T] = new Stream[T] {
    def head = hd
    private var t1Opt: Option[Stream[T]] = None
    def tail: Stream[T] = t1Opt match {
      case Some(x) => x
      case None => t1Opt = Some(t1); tail
    }
  }

  def streamIncrementedby2(x: Int): Stream[Int] = x #:: streamIncrementedby2(x + 2)

  val x = this.cons(-1, this.streamIncrementedby2(5))
  println(x.head)

}

我正在尝试 courera odersky 课程中的示例:scala 功能设计 week3 视频。有趣的是,在上面的例子中,如果我删除第一个 println 语句下面的所有内容,我会看到一个评估的输出。

******** 更新******** 为了帮助其他读者,我发布了上述程序的更正版本,受到答案的启发。

 def cons[T](hd: T, t1: => Stream[T]) = new Stream[T] {
    override def head = hd
    override def isEmpty = false
    private[ this ] var t1Opt: Option[Stream[T]] = None
    def tailDefined: Boolean = true
    override def tail: Stream[T] = t1Opt match {
      case Some(x) => x
      case None => {t1Opt = Some(t1); tail}
    }
  } 

【问题讨论】:

  • 也许您没有看到错误?我收到此错误error: illegal inheritance from sealed class Stream(您没有描述您要归档的内容,所以我不确定如何给出答案)
  • 我正在尝试定义一个方法 cons,它接受一个流和一个元素 hd 并使元素成为流的头部。
  • 您的解决方案并没有真正回答问题。如果 Scala 工作表真的不起作用,那么在编辑器中修改代码应该不会有任何效果。你做了什么来修复工作表?如果工作表实际上工作正常,那么也许您应该更正问题的标题。寻求帮助以修复损坏的工作表的人会发现您的问题/答案有帮助吗?
  • 我编辑了问题标题。当我发布问题时,我实际上觉得工作表有些问题,因为我在 eclipse 的任何地方都看不到任何编译错误,只是工作表没有显示任何输出。

标签: scala scala-streams


【解决方案1】:

如果你只想做一个Stream的通用元素头,你可以使用Stream包中的现有方法cons

def streamIncrementedby2( x: Int ): Stream[ Int ] = x #:: streamIncrementedby2( x + 2 )

val x = Stream.cons( -1, this.streamIncrementedby2( 5 ) )
println( x.head )

它工作正常。但是,如果您想制作自己的版本,则必须深入挖掘。通过使用以下函数定义,您正在制作 构造函数,而不是普通函数

def cons[T](hd: T, t1: => Stream[T]): Stream[T] = new Stream[T] { ...

这里的关键是= new Stream[T]。因此,您必须提供很多合适的构造函数需要的东西:覆盖抽象函数,如headtailisEmpty,并提供必要的函数tailDefined

def classCons[ T ]( hd: T, t1: => Stream[ T ] ): Stream[ T ] = new Stream[ T ] {

    override def isEmpty = false
    override def head = hd
    private[ this ] var tlVal: Stream[ T ] = _

    def tailDefined: Boolean = tlVal ne null

    override def tail: Stream[T] = {

        if ( !tailDefined )
            synchronized {
                if ( !tailDefined ) 
                    tlVal = t1
            }

        tlVal
    }
}

inspiration

您还可以使您的 cons 函数成为一个普通函数并获得相同的结果,而不会弄乱构造函数。

def funcCons[ T ]( hd: T, t1: => Stream[ T ] ): Stream[ T ] =  {

    if ( t1.isEmpty )
        Stream( hd )
    else 
        hd #:: t1.tail
}

结果是一样的:

val ccStream = classCons( -1, this.streamIncrementedby2( 5 ) )
val ffStream = funcCons( -1, this.streamIncrementedby2( 5 ) )
println( ccStream.head )
println( ffStream.head )
// Result => -1
// Result => -1

【讨论】:

  • 谢谢。那很有帮助。我用解决方案更新了上面的问题。您的解决方案也有效。我意识到 [this] 在私有变量中确实是必需的。没有[这个]就行不通。为什么需要this。您还看到 Odersky 教授方法的任何优势,他将尾巴包裹在 Option 中。你的方法更清晰。最后,您的解决方案中 = _ 的用途是什么。抱歉,我还在学习。
  • private[this] 限制对该字段的访问,因此没有其他类实例可以更改它。因为它被用作同步状态,所以它很重要。 var tlVal: Stream[ T ] = _tlVal 初始化为Stream[T] 的默认值,该默认值基本上为空。当值可以为空时使用选项,因此这是安全措施。在此示例中无关紧要,但通常最好使用 Option 而不是 null 以获得更多受控代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-29
  • 2016-03-16
  • 1970-01-01
  • 1970-01-01
  • 2014-12-31
  • 2021-11-29
  • 1970-01-01
相关资源
最近更新 更多