Function / method equality in scala

Hello, is it possible to check if a method / function reference matches another in scala? For example, to write a function like the following and get the truth?

scala> def m = 1
m: Int

scala> def check(p: () => Int): Boolean = p == m _
check: (p: () => Int)Boolean              

scala> check(m _)
res0: Boolean = false

      

+1


source to share


2 answers


Summary:
Yes, it is possible to check the correspondence between two specific referenced links in Scala, but not quite in the way you stated your problem. You just need to capture the specific function of the object, class, or trait reference (not lambda, anonymous function, etc.).

Details:
Since Scala has the concept of a function reference, it is possible to test two different function references for reference equality. And since Scala also provides a mechanism to get a function reference from any valid Scala method, that means you can probably do what you were trying to do, given your question on mz's answer, "... there is no way to get a reference or something like that for a method? "

It is important to remember that two functions can only be checked for reference equality. IOW, to functions CANNOT be checked for equality of the function definition (which you really don't want anyway for the Pandora block of unwanted unsolvable tangents it generated).

So, below I found out about this specifically and precisely. I used a Scala table (2.11.7) in IntelliJ (15.0.3) to create the following test scenarios.

First, the failure path, compile time and run time:



object ConcreteMethods1 {
  def intToStringNone(string: String): Option[Int] =
    None

  def intToStringSome1(string: String): Option[Int] =
    Some(1)
}
//def someMethodFailureCompileTime(
//    parseFunctionReference: String => Option[Int]
//): (Boolean, Boolean) = {
//  (
//      parseFunctionReference == ConcreteMethods1.intToStringNone
//    , parseFunctionReference == ConcreteMethods1.intToStringSome1
//    )
//}
def someMethodFailureRuntime(
    parseFunctionReference: String => Option[Int]
): (Boolean, Boolean) = {
  val intToStringNoneFunctionReference: String => Option[Int] =
    ConcreteMethods1.intToStringNone
  val intToStringSome1FunctionReference: String => Option[Int] =
    ConcreteMethods1.intToStringSome1
  (
      parseFunctionReference == intToStringNoneFunctionReference
    , parseFunctionReference == intToStringSome1FunctionReference
  )
}
val someMethodNoneFailureRuntime =
  someMethodFailureRuntime(ConcreteMethods1.intToStringNone)
  //want (true, false), but get (false, false)
val someMethodSome1FailureRuntime =
  someMethodFailureRuntime(ConcreteMethods1.intToStringSome1)
  //want (false, true), but get (false, false)

      

Second, the success path (which implies both compile time and runtime):

object ConcreteMethods2 {
  def intToStringNone(string: String): Option[Int] =
    None

  def intToStringSome1(string: String): Option[Int] =
    Some(1)

  val intToStringNoneFunctionReference: String => Option[Int] =
    intToStringNone

  val intToStringSome1FunctionReference: String => Option[Int] =
    intToStringSome1
}
def someMethodSuccess(
    parseFunctionReference: String => Option[Int]
): (Boolean, Boolean) = {
  (
      parseFunctionReference == ConcreteMethods2.intToStringNoneFunctionReference
    , parseFunctionReference == ConcreteMethods2.intToStringSome1FunctionReference
  )
}
val someMethodNoneSuccess =
  someMethodSuccess(ConcreteMethods2.intToStringNoneFunctionReference)
val someMethodSome1Success =
  someMethodSuccess(ConcreteMethods2.intToStringSome1FunctionReference)

      

And you have it by checking equality between two specific referenced references in Scala. This little trick helped solve the basic recursion problem. I was trying to write generic parsing code that was parsing from iterating over the strings at the root. I was able to use this particular equality reversal function to end the recursion.

+1


source


There is no such thing as a method reference. When you write m _

, you are using eta-expand m

for the function. A new instance of the function.

You can refer to validation functions (assigned by vals or vars), but only by reference.

def m = 1

val mx = m _
val my = m _ // not the same function as `mx` !
val mz = mx

scala> mx == mx
res4: Boolean = true

scala> mx == my
res5: Boolean = false

scala> mz == mx
res6: Boolean = true

      



mx

is equal to itself (by reference), but although logically equivalent my

, it was created by a separate ethical extension and therefore does not have referential equality. mz

, on the other hand, has the same link as mx

.

The bottom line is that comparing a new reference-extended method with another function will always give false. Even if it's on its own.

scala> m _ == m _
<console>:12: warning: comparing a fresh object using `==' will always yield false
       m _ == m _
           ^
res10: Boolean = false

      

+5


source







All Articles