0

I have a class with an unknown number of functions:

class processors {
  def p1(s: String): String = {
    //code
  }
  def p2(s: String): String = {
    //code
  }
  def p3(s: String): String = {
    //code
  }
  ...
}

I want to be able to run all the function one by one in the order they are written (p1 -> p2 -> p3 -> ...). Also, I would like to pass the initial string to p1, which will pass the result as the argument for p2 and do on. Is there a simple way to do that?

EDIT:

What I have so far:

At the moment I have a hard-coded sequence:

val processors = Seq(p1 _, p2 _, p3 _).reduce(_ andThen _)
processors(some_string)

I'd like to avoid the hard-coding, basically..

shakedzy
  • 2,853
  • 5
  • 32
  • 62
  • 1
    Do you control the class? Do you know how many methods it has? If you don't (as you say *unknown* in your question), how exactly do you invoke them now? – Yuval Itzchakov Aug 26 '16 at 13:03
  • If you don't return a processor in each function, I doubt you can call the function is this wait p1 -> p2 -> p3. You should explain in a better way the current question. You can probably define something like: def p1(s:String):processor = {} def p2(s:processor): processor{} def p3(s:processor):processor{} you can add a value corresponding to the current String value every time processor is changed the corretValue can be changed. – ypriverol Aug 26 '16 at 13:12
  • `def run(s: String): String = p3(p2(p1(s))) // jokes on you :)` If you don't know the number of steps just use reflection API to get all methods, throw them into a list and call one by one recursively passing the String as accumulator. – sebszyller Aug 26 '16 at 13:16
  • I've edited the post, showing what I use so far. I'd like refrain from using `var`s, as this will run on Spark.. – shakedzy Aug 26 '16 at 13:20
  • When you say "hard to avoid hard-coding", do you mean you don't want to explicitly mention each new added method? – Yuval Itzchakov Aug 26 '16 at 13:21
  • @YuvalItzchakov : exactly – shakedzy Aug 26 '16 at 13:22
  • What about macro annotation for `processors` class, that will find all `pN-like` methods in compile-time and generate additional combined method? – dveim Aug 26 '16 at 13:36

1 Answers1

2

Reflection can help here. this example is for single param integer argument, but it can be extended to multiple arguments but it gets bit tricky dealing with types. Argument types can be queried from the class.

class A {
  def f(x: Int): Int = 2 * x
  def g(x: Int): Int = x * x
}

val clazz = classOf[A]

clazz.getDeclaredMethods.filter(! _.getName.contains("$"))
.map(x => {a: Integer => x.invoke(new A(), a: Integer).asInstanceOf[Integer] })
.reduce(_ andThen _)(new Integer(1))

For your case just replace Int with String

To maintain the order of execution of the functions in the class

try to put number in the function name and then order them by parsing string obtained from getName method

Nagarjuna Pamu
  • 14,737
  • 3
  • 22
  • 40
  • That's exactly what I said I do not want to do – shakedzy Aug 26 '16 at 13:24
  • @shakedzy . Edited the answer. hope this helps you. – Nagarjuna Pamu Aug 26 '16 at 13:44
  • Here three ways: 1) hard code 2) java or scala reflection 3) macro annotation: `@procontainer class processors`. see – user1303559 Aug 26 '16 at 14:01
  • @shakedzy Result type of an implicit conversion must be more specific than AnyRef. http://stackoverflow.com/questions/26546299/result-type-of-an-implicit-conversion-must-be-more-specific-than-anyref – Nagarjuna Pamu Aug 26 '16 at 14:28
  • @pamu I would appreciate if you could edit your answer, so the code will compile. I don't understand what you're trying to point at – shakedzy Aug 26 '16 at 15:57
  • @shakedzy edited the answer with working solution. Please tell me if this is useful to you – Nagarjuna Pamu Aug 26 '16 at 17:24
  • @pamu I'm getting `java.lang.IllegalArgumentException: wrong number of arguments`, probably from the `andThen` part – shakedzy Aug 26 '16 at 21:50
  • 1
    @pamu fixed it. just adding `clazz.getDeclaredMethods.filter(! _.getName.contains("$"))` in order to remove Scala created methods. Thanks! – shakedzy Aug 26 '16 at 21:58
  • @pamu It doesn't keep an order. I can sometimes be `p1 -> p2 -> p3` and another `p2 -> p3 -> p1`.. The order is important in my case – shakedzy Aug 26 '16 at 23:20
  • 1
    @shakedzy try to put number in the function name and then order them by parsing string obtained from `getName` method. – Nagarjuna Pamu Aug 27 '16 at 08:38