Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala编译器说,如果使用隐式和匿名类,我的方法是递归的_Scala_Dsl_Anonymous Class_Higher Order Functions_Implicits - Fatal编程技术网

Scala编译器说,如果使用隐式和匿名类,我的方法是递归的

Scala编译器说,如果使用隐式和匿名类,我的方法是递归的,scala,dsl,anonymous-class,higher-order-functions,implicits,Scala,Dsl,Anonymous Class,Higher Order Functions,Implicits,我希望能够像这样编写代码 10 times { doSomething } 所以我想我可以用它来做 当我在Scala REPL中执行以下代码时,它得到了正确的定义 scala> implicit def intToMyRichInt(count: Int) = { | new { | def times(f: => Unit) = { | 1 to count foreach { _ => f } |

我希望能够像这样编写代码

10 times {
   doSomething
}
所以我想我可以用它来做

当我在Scala REPL中执行以下代码时,它得到了正确的定义

scala> implicit def intToMyRichInt(count: Int) = {
    |     new {
    |       def times(f: => Unit) = {
    |         1 to count foreach { _ => f }
    |       }
    |     }
    |   }
但是当我尝试编译时

object Test {
    implicit def intToMyRichInt(count: Int) = {
      new {
        def times(f: => Unit) = {
           1 to count foreach { _ => f }
      }
   }
}
它因错误而失败

error: recursive method intToMyRichInt needs result type
1 to count foreach { _ => f }

有什么区别?我做错了什么?

我认为scala无法推断递归函数的返回类型,原因我曾经知道,但现在忘记了


但在您的情况下,我可以成功编译该文件,除非它再错过一个}

通过删除def的{修复代码后,它编译得很好:

scala> object Test {
     |     implicit def intToMyRichInt(count: Int) = {
     |       new {
     |         def times(f: => Unit) =
     |            1 to count foreach { _ => f }
     |       }
     |    }
     | }
defined module Test
还建议删除隐式定义后面的{}:

object Test {
    implicit def intToMyRichInt(count: Int) = 
      new {
        def times(f: => Unit) = 
           1 to count foreach { _ => f }
      }   
}
另外,值得一提的是,新的{…class content…}实际上是编译器的一种结构类型,因此对times的调用将进行反射。解决方法之一是创建一个新类:

object Test {
    class MyRichInt(x:Int) {
      def times(f: => Unit) =  1 to x foreach { _ => f }
    }
    implicit def intToMyRichInt(count: Int) = new MyRichInt(count)
}

希望已经回答了您的问题。

不幸的是,pedrofurla建议的解决方案似乎不起作用(至少在2.8.0决赛中是这样):

对象测试{
隐式def intomyrichint(计数:Int)=
新ScalaObject{
def次数(f:=>单位)=
1来计算每个{{u0=>f}
}
def foo=10.5倍{println(“foo”)}
}
F:\MyProgramming\raw>scalac-Xprint:jvm Main.scala
[[jvm末尾的语法树]]//Scala源代码:Main.Scala
包装{
最后一个类测试使用ScalaObject扩展了java.lang.Object{
最终私有变量reflParams$Cache1:Array[java.lang.Class]=Array[java.lang.Class]{classOf[scala.Function0]};
@volatile private var reflPoly$Cache1:java.lang.ref.SoftReference=new java.lang.ref.SoftReference(new scala.runtime.EmptyMethodCache());
def reflMethod$Method1(x$1:java.lang.Class):java.lang.reflect.Method={
if(Test.reflPoly$Cache1.get().$asInstanceOf[scala.runtime.MethodCache]().eq(null))
Test.reflPoly$Cache1=new java.lang.ref.SoftReference(new scala.runtime.EmptyMethodCache());
var method1:java.lang.reflect.Method=Test.reflPoly$Cache1.get().$asInstanceOf[scala.runtime.MethodCache]().find(x$1);
if(method1.ne(null))
返回方法1
其他的
{
method1=x$1.getMethod(“times”,Test.reflParams$Cache1);
Test.reflPoly$Cache1=new java.lang.ref.SoftReference(Test.reflPoly$Cache1.get().$asInstanceOf[scala.runtime.MethodCache]().add(x$1,method1));
返回方法1
}
};
隐式def intToMyRichInt(count$1:Int):ScalaObject=newtest$$anon$1(count$1);
def foo():单位={
{
val qual1:ScalaObject=Test.this.intomyrichint(10);
{
{
var exceptionResult1:java.lang.Object=\uU4;
试一试{
exceptionResult1=Test.reflMethod$Method1(qual1.getClass()).invoke(qual1,数组[java.lang.Object]{{
(新测试$$anonfun$foo$1():函数0)
}})
}抓住{
case($1$@(551;:java.lang.reflect.InvocationTargetException))=>{
exceptionResult1=抛出$1$.getCause()
}
};
例外结果1
};
scala.runtime.BoxedUnit.UNIT
}
};
()
};
def this():对象测试={
Test.reflParams$Cache1=Array[java.lang.Class]{classOf[scala.Function0]};
Test.reflPoly$Cache1=new java.lang.ref.SoftReference(new scala.runtime.EmptyMethodCache());
Test.super.this();
()
}
};
@SerialVersionUID(0)@serializable最终类测试$$anon$1$$anonfun*$1扩展了scala.runtime.AbstractFunction1$mcVI$sp{
最终def应用(x$1:Int):单位=测试$$anon$1$$anonfun*$1。此。应用$mcVI$sp(x$1);
def apply$mcVI$sp(v1:Int):Unit=Test$$anon$1$$anonfun*$1.f$1.apply$mcV$sp();
最终定义应用(v1:java.lang.Object):java.lang.Object={
Test$$anon$1$$anonfun*$1.this.apply(scala.Int.unbox(v1));
scala.runtime.BoxedUnit.UNIT
};
private[this]val f$1:Function0=\u0;
定义此($outer:Test$$anon$1,f$1:Function0):Test$$anon$1$$anonfun*$1={
测试$$anon$1$$anonfun*$1。此.f$1=f$1;
Test$$anon$1$$anonfun*$1.super.this();
()
}
};
最终类测试$$anon$1使用ScalaObject扩展了java.lang.Object{
def times(f$1:Function0):Unit=scala.this.Predef.intWrapper(1.to)(Test$$anon$1.this.count$1)。$asInstanceOf[scala.collection.immutable.Range$ByOne]()。foreach$mVc$sp({
(新测试$$anon$1$$anonfun*$1(测试$$anon$1.this,f$1):功能1)
});
private[this]val count$1:Int=\;
定义此(计数$1:Int):测试$$anon$1={
Test$$anon$1。this.count$1=count$1;
Test$$anon$1.super.this();
()
}
};
@SerialVersionUID(0)@serializable最终类测试$$anonfun$foo$1扩展了scala.runtime.AbstractFunction0$mcV$sp{
final def apply():Unit=Test$$anonfun$foo$1.this.apply$mcV$sp();
def apply$mcV$sp():Unit=scala.this.Predef.println(“foo”);
final def apply():java.lang.Object={
Test$$anonfun$foo$1.this.apply();
scala.runtime.BoxedUnit.UNIT
};
def this():Test$$anonfun$foo$1={
Test$$anonfun$foo$1.super.this();
()
}
}
}

@tbruhn:我无法验证您的问题,它在这里编译得很好

我怀疑您使用的是一些过时的Scala版本,可能吧

如果是这样的话,显而易见的修复方法是升级到Scala 2.8.x


否则,如何编译?如果您是通过IDE编译,请尝试查看
scalac
是否存在相同的错误。

编译器无法推断递归函数/方法的结果类型。推断取决于结果表达式的类型。在递归函数中,结果表达式通常是函数本身如果,在这种情况下,如果还不知道该类型如何推断?但正如@the_great_monkey所指出的,问题并非如此。我最初很兴奋,但这
object Test {
    implicit def intToMyRichInt(count: Int) = 
      new ScalaObject {
        def times(f: => Unit) = 
           1 to count foreach { _ => f }
      }

    def foo = 10.times { println("foo") }
}

F:\MyProgramming\raw>scalac -Xprint:jvm Main.scala
[[syntax trees at end of jvm]]// Scala source: Main.scala
package <empty> {
  final class Test extends java.lang.Object with ScalaObject {
    final private <synthetic> <static> var reflParams$Cache1: Array[java.lang.Class] = Array[java.lang.Class]{classOf[scala.Function0]};
    @volatile private <synthetic> <static> var reflPoly$Cache1: java.lang.ref.SoftReference = new java.lang.ref.SoftReference(new scala.runtime.EmptyMethodCache());
    <synthetic> <static> def reflMethod$Method1(x$1: java.lang.Class): java.lang.reflect.Method = {
      if (Test.reflPoly$Cache1.get().$asInstanceOf[scala.runtime.MethodCache]().eq(null))
        Test.reflPoly$Cache1 = new java.lang.ref.SoftReference(new scala.runtime.EmptyMethodCache());
      var method1: java.lang.reflect.Method = Test.reflPoly$Cache1.get().$asInstanceOf[scala.runtime.MethodCache]().find(x$1);
      if (method1.ne(null))
        return method1
      else
        {
          method1 = x$1.getMethod("times", Test.reflParams$Cache1);
          Test.reflPoly$Cache1 = new java.lang.ref.SoftReference(Test.reflPoly$Cache1.get().$asInstanceOf[scala.runtime.MethodCache]().add(x$1, method1));
          return method1
        }
    };
    implicit def intToMyRichInt(count$1: Int): ScalaObject = new Test$$anon$1(count$1);
    def foo(): Unit = {
      {
        val qual1: ScalaObject = Test.this.intToMyRichInt(10);
        {
          {
            var exceptionResult1: java.lang.Object = _;
            try {
              exceptionResult1 = Test.reflMethod$Method1(qual1.getClass()).invoke(qual1, Array[java.lang.Object]{{
                (new Test$$anonfun$foo$1(): Function0)
              }})
            } catch {
              case ($1$ @ (_: java.lang.reflect.InvocationTargetException)) => {
                exceptionResult1 = throw $1$.getCause()
              }
            };
            exceptionResult1
          };
          scala.runtime.BoxedUnit.UNIT
        }
      };
      ()
    };
    def this(): object Test = {
      Test.reflParams$Cache1 = Array[java.lang.Class]{classOf[scala.Function0]};
      Test.reflPoly$Cache1 = new java.lang.ref.SoftReference(new scala.runtime.EmptyMethodCache());
      Test.super.this();
      ()
    }
  };
  @SerialVersionUID(0) @serializable final <synthetic> class Test$$anon$1$$anonfun*$1 extends scala.runtime.AbstractFunction1$mcVI$sp {
    final def apply(x$1: Int): Unit = Test$$anon$1$$anonfun*$1.this.apply$mcVI$sp(x$1);
    <specialized> def apply$mcVI$sp(v1: Int): Unit = Test$$anon$1$$anonfun*$1.this.f$1.apply$mcV$sp();
    final <bridge> def apply(v1: java.lang.Object): java.lang.Object = {
      Test$$anon$1$$anonfun*$1.this.apply(scala.Int.unbox(v1));
      scala.runtime.BoxedUnit.UNIT
    };
    <synthetic> <paramaccessor> private[this] val f$1: Function0 = _;
    def this($outer: Test$$anon$1, f$1: Function0): Test$$anon$1$$anonfun*$1 = {
      Test$$anon$1$$anonfun*$1.this.f$1 = f$1;
      Test$$anon$1$$anonfun*$1.super.this();
      ()
    }
  };
  final class Test$$anon$1 extends java.lang.Object with ScalaObject {
    def times(f$1: Function0): Unit = scala.this.Predef.intWrapper(1).to(Test$$anon$1.this.count$1).$asInstanceOf[scala.collection.immutable.Range$ByOne]().foreach$mVc$sp({
      (new Test$$anon$1$$anonfun*$1(Test$$anon$1.this, f$1): Function1)
    });
    <synthetic> <paramaccessor> private[this] val count$1: Int = _;
    def this(count$1: Int): Test$$anon$1 = {
      Test$$anon$1.this.count$1 = count$1;
      Test$$anon$1.super.this();
      ()
    }
  };
  @SerialVersionUID(0) @serializable final <synthetic> class Test$$anonfun$foo$1 extends scala.runtime.AbstractFunction0$mcV$sp {
    final def apply(): Unit = Test$$anonfun$foo$1.this.apply$mcV$sp();
    <specialized> def apply$mcV$sp(): Unit = scala.this.Predef.println("foo");
    final <bridge> def apply(): java.lang.Object = {
      Test$$anonfun$foo$1.this.apply();
      scala.runtime.BoxedUnit.UNIT
    };
    def this(): Test$$anonfun$foo$1 = {
      Test$$anonfun$foo$1.super.this();
      ()
    }
  }
}