Scala隐式类(在隐式类内部使用隐式)-不是Int错误的成员

时间:2019-07-17 07:38:01

标签: scala implicit

我想用scala(递归)编写一个totient-function

  

Euler的totient函数对直到给定整数n的正整数进行计数,这些整数相对于n

我想到了:

object Totient {
  implicit class Improvements(val number: Int) {
    def totient: Int = {
      @tailrec
      def helper(currentN: Int, accumulator: Int): Int =
        if (currentN == 1) accumulator
        else {
          if (number.isDividable(currentN)) helper(currentN - 1, accumulator)
          else helper(currentN - 1, accumulator + 1)
        }
      helper(number, 0)
    }

    private def isDividable(divisor: Int) = number % divisor == 0
  }
}

出于可读性考虑,我创建了一个小函数isDividable。 我想在递归helper方法中使用此函数。 不幸的是,我收到以下错误:

Error:(12, 22) value isDividable is not a member of Int
      if (number.isDividable(currentN)) helper(currentN - 1, accumulator)  

问题:有人可以向我解释,我做错了什么以及如何解决?

编辑:

为完整起见,我将添加totient函数的有效实现:

object Totient {
  implicit class Improvements(val number: Int) {
    def totient: Int = {
      @tailrec
      def helper(currentN: Int, accumulator: Int): Int =
        if (currentN == 0) accumulator
        else {
          if (number.isCoprimeTo(currentN)) helper(currentN - 1, accumulator + 1)
          else helper(currentN - 1, accumulator)
        }
      helper(number, 0)
    }

    private[Totient] def isCoprimeTo(otherNumber: Int): Boolean = {
      gcd(number, otherNumber) == 1
    }

    private def gcd(firstNumber: Int, secondNumber: Int): Int =
      if (secondNumber == 0) firstNumber else gcd(secondNumber, firstNumber % secondNumber)
  }
}

2 个答案:

答案 0 :(得分:4)

private没有额外的信息意味着“只有通过其他改进方法才能访问,但是对于相同的改进实例”。

这意味着您可以调用isDividable来获得与调用totient / helper相同的number的结果,但是它不会成为扩展方法(因为在外部看不到)改进)。

为解决此问题,您可以更改方法的范围,例如使它对Totient中定义的所有方法可见:

object Totient {
  implicit class Improvements(val number: Int) {
    def totient: Int = {
      @tailrec
      def helper(currentN: Int, accumulator: Int): Int =
        if (currentN == 1) accumulator
        else {
          if (number.isDividable(currentN)) helper(currentN - 1, accumulator)
          else helper(currentN - 1, accumulator + 1)
        }
      helper(number, 0)
    }

    // notice [Totient] after private
    private[Totient] def isDividable(divisor: Int) = number % divisor == 0
  }
}

这会在我的炸药中编译并起作用:

@ import Totient._ 
import Totient._

@ 12.totient 
res2: Int = 6

答案 1 :(得分:0)

另一种选择是从isDividable而不是isCoprimeTo调用this / number。这样,编译器根本不必执行隐式解析即可获取该方法。使用您的原始代码:

    def totient: Int = {
      @tailrec
      def helper(currentN: Int, accumulator: Int): Int =
        if (currentN == 1) accumulator
        else {
          if (this.isDividable(currentN)) helper(currentN - 1, accumulator)
          else helper(currentN - 1, accumulator + 1)
        }
      helper(number, 0)
    }

(您甚至可以完全忽略对this的调用,而只需拥有isDividable(currentN),但这会使代码不太清晰。)