Scala compiler says my method is recursive when using implicit and anonymous class

I want to be able to write code like

10 times {
   doSomething
}

So, I thought I could do it with implicits.

When I execute the following code in Scala REPL, it is correctly detected

scala> implicit def intToMyRichInt(count: Int) = {
    |     new {
    |       def times(f: => Unit) = {
    |         1 to count foreach { _ => f }
    |       }
    |     }
    |   }

However, when I try to compile,

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

he fails with an error

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

What is the difference? What am I doing wrong?

+3
source share
4 answers

After fixing the code, deleting def {, it compiled just fine:

scala> object Test {
     |     implicit def intToMyRichInt(count: Int) = {
     |       new {
     |         def times(f: => Unit) =
     |            1 to count foreach { _ => f }
     |       }
     |    }
     | }
defined module Test

It is also recommended that you remove {} after the implicit def:

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

, , {... class content...} , . :

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

.

+2

@tbruhn: , .

, Scala, ?

Scala 2.8.x!

, ? IDE, , scalac .

+1

, scala , - , .

But in your case, I can compile the file successfully, except that it missed another one}.

0
source

Unfortunately, the workaround suggested by pedrofurla does not seem to work (at least in the final 2.8.0):

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();
      ()
    }
  }
}
0
source

Source: https://habr.com/ru/post/1771007/


All Articles