scala – 持续和理解 – 什么是不兼容性?
我是新来的
Scala,试图围绕着我的头脑
我正在尝试重现产量返回C#语句. 在this post之后,我写了下面的代码: package com.company.scalatest import scala.util.continuations._; object GenTest { val gen = new Generator[Int] { def produce = { yieldValue(1) yieldValue(2) yieldValue(3) yieldValue(42) } } // Does not compile :( // val gen2 = new Generator[Int] { // def produce = { // var ints = List(1,2,3,42); // // ints.foreach((theInt) => yieldValue(theInt)); // } // } // But this works? val gen3 = new Generator[Int] { def produce = { var ints = List(1,42); var i = 0; while (i < ints.length) { yieldValue(ints(i)); i = i + 1; } } } def main(args: Array[String]): Unit = { gen.foreach(println); // gen2.foreach(println); gen3.foreach(println); } } abstract class Generator[E] { var loopFn: (E => Unit) = null def produce(): Unit @cps[Unit] def foreach(f: => (E => Unit)): Unit = { loopFn = f reset[Unit,Unit](produce) } def yieldValue(value: E) = shift { genK: (Unit => Unit) => loopFn(value) genK(()) () } } 你可以看到,gen2被注释掉,因为它没有编译.由于我可以轻松地使用while循环遍历列表的内容(见gen3),所以我预计foreach循环也是一样. 编译错误如下: no type parameters for method foreach: (f: Int => B)Unit exist so that it can be applied to arguments (Int => Unit @scala.util.continuations.cpsParam[Unit,Unit]) --- because --- argument expression's type is not compatible with formal parameter type; found : Int => Unit @scala.util.continuations.cpsParam[Unit,Unit] required: Int => ?B 为什么我得到这个错误,有没有办法解决这个比一个比循环更干净的东西? 谢谢 解决方法
首先让我们来看看gen2编译需要做什么.
object CpsConversions { import scala.collection.IterableLike import scala.util.continuations._ implicit def cpsIterable[A,Repr](xs: IterableLike[A,Repr]) = new { def cps = new { def foreach[B](f: A => Any@cpsParam[Unit,Unit]): Unit@cpsParam[Unit,Unit] = { val it = xs.iterator while(it.hasNext) f(it.next) } } } } object GenTest { import CpsConversions.cpsIterable val gen2 = new Generator[Int] { def produce = { var ints = List(1,42) ints.cps.foreach((theInt) => yieldValue(theInt)) } } 现在来看看发生了什么.原始gen2无法在以下行中编译: ints.foreach((theInt) => yieldValue(theInt)) 由于yieldValue的类型包含一个@cpsParam注释,所以继承插件将传递给foreach方法的函数转换为以下类型之一: Int => Unit @cpsParam[Unit,Unit] 在列表[Int]的层次结构中,您将看到foreach定义为: foreach [U] (f: (Int) ? U): Unit 这是一个问题,因为类型不匹配,Scala不知道如何从Int => U到Int =>单位@cpsParam [Unit,Unit].为了解决这个问题,我在一个隐式转换中添加了foreach的CPS版本,你可以通过调用任何IterableLike上的cps来访问它. 如果这种隐式转换可以在没有明确的cps调用的情况下完成,那么这将是非常好的,但是我还没有找到一种方法来使Scala编译器识别这种隐式转换的可用性,以将新的foreach复制到列表中.这可能与编译器使用连续插件的顺序有关,但我知道这个过程太少了,以确保. 所以这一切都很好,对foreach有好处.您的问题提到了解,这将需要定义任何过滤器,地图或平面图(取决于您的理解情况).我在上面的评论中已经实现了这些,它扩展了上面的CpsConversions对象,以允许一般的理解. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |