Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a class method as a parameter in Scala

Tags:

scala

Lets say I have a class C with some methods

def class C {
  def f1():Int = ...
  def f2():Int = ...
}

Now I'd like a method that takes two instances of C, as well as a method of C, but I don't know what the types of f1, f2 are, nor how to invoke them. I'm thinking it would look something like

def cmp(first:C, second:C, t:() => Int): Boolean = {
  first.t < second.t
}

This complains that t is not a method of C. Surely there must be a way to express this.

like image 715
Mike Kraley Avatar asked Jul 01 '13 23:07

Mike Kraley


People also ask

What is the meaning of => in Scala?

=> is syntactic sugar for creating instances of functions. Recall that every function in scala is an instance of a class. For example, the type Int => String , is equivalent to the type Function1[Int,String] i.e. a function that takes an argument of type Int and returns a String .

What kind of parameters are not needed while calling a method in Scala?

A parameterless method is a function that does not take parameters, defined by the absence of any empty parenthesis. Invocation of a paramaterless function should be done without parenthesis.


2 Answers

def cmp(first:C, second:C, t: C => Int): Boolean = {
  t(first) < t(second)
}

Then...

val c1 = new C
val c2 = new C
cmp(c1, c2, _.f1())
cmp(c1, c2, _.f2())

This is using anonymous functions. The last two lines are equivalent to:

cmp(c1, c2, {c: C => c.f1()})
cmp(c1, c2, {c: C => c.f2()})

You can't pass a reference to a method per se unless you use some kind of reflection.

like image 160
ghik Avatar answered Oct 04 '22 03:10

ghik


You can just pass the method references instead:

object DoOperation extends App {

  class C(val x: Int) {
      def f1():Int = x-1
      def f2():Int = x+1
   }


  def cmp(first: () => Int, second: () => Int): Boolean = {
    first() < second()
  }

  override def main(args: Array[String]) {
      println(cmp(new C(1).f1,new C(0).f2)) //prints "true"
      println(cmp(new C(1).f2,new C(1).f1)) //prints "false"
  }

}

The methods will be closed over their corresponding object instances, so the net effect is the equivalent to what you appear to want to accomplish.

like image 42
mikołak Avatar answered Oct 04 '22 03:10

mikołak