Scala Implicit class(在 implicit class 中使用 implicits)- 不是 Int 错误的成员

Scala Implicit class (using implicits inside implicit class) - Not a member of Int error

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

Euler's totient function counts the positive integers up to a given integer n that are relatively prime to 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)
  }
}

private 没有额外信息意味着这里 "accessible only by other methods of Improvements but for the same instance of Improvements".

这意味着您可以调用 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

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

    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),但这会使代码不那么清晰。)