0

Scenario is as follows :

Main class reads inputs values (e.g. A, B, C, D) from a LIST iteratively.

Another class contains implementation of separate methods to handle these input values accordingly. E.g. Method A can be called only if input value is A, method B can be called only if input value is B.

The good part is that all these methods accept exactly same parameter and its types. e.g. A, B, C, are all of same type.

Is there any way to handle this in Scala?

We can use ENUM and case logic but looking for a better way to do this? E. G. Scala reflection API or using case classes.

6
  • If A,B,C,D are all of the same type, then why not use one method to handle all of them and decide the output of the aforementioned function with an if or match-case? Commented Feb 25, 2018 at 16:13
  • Although what you said is possible but match case to handle everything in a same method will get complex over a period of time since list values could go beyond 10.. e. g. A, B, C, D, E, F, G, H, I, J... n Commented Feb 25, 2018 at 18:03
  • If it's more than 10, then it's probably not so much about inconvenient syntax. So, how many classes are we actually talking about, and what do those "separate methods" in "another class" look like? Did you consider code generation? Commented Feb 25, 2018 at 18:23
  • @AndreyTyukin , kindly can you please guide on code generation ? will try it. There are only two classes ( Class C1 which contains main method ) and Class C2 which contains the methods implementations equal to the number of the possible LIST values . Commented Feb 27, 2018 at 20:25
  • @Kaa codegen is essentially very simple: you just write a program that writes the boilerplate in your program. The interesting part is how to persuade your build system to trigger the generation before the compilation, and then to pick up the generated files and compile them with the rest of your code. So, all the interesting steps are pretty much dependent on the build system. Do you use sbt? Could you provide more details about what those A, B, C... Z classes actually look like, and what the methods in C2 are? Commented Feb 27, 2018 at 20:47

1 Answer 1

1

From your question, it's not at all obvious why you would want to use dynamic invocation or reflection.


If all values A, ..., D belong to a common type Foo, then it probably won't get much easier than with case-classes:

sealed trait Foo
case class A(a1: Int, a2: String) extends Foo
case class B(b: Double) extends Foo
case class C(c: String) extends Foo
case object D extends Foo

Every time you want to transform A, ..., D to some other result type R, you can simply write a match-case, and handle the different cases there. If you use it so often that it is still too verbose, you can introduce an eliminator of the type Foo, which accepts bunch of functions, and hides the pattern matching inside:

object Foo {
  def elim[R](
    aElim: (Int, String) => R,
    bElim: Double => R,
    cElim: String => R,
    dElim: R
  )(f: Foo): R = f match {
    case A(a1, a2) => aElim(a1, a2)
    case B(b) => bElim(b)
    case C(s) => cElim(s)
    case D => dElim
  }
}

In this way, you can trade the naming of the cases in match-case for a shorter syntax, e.g. you could construct an eliminator like this:

val fooToString = Foo.elim(_ + _, "" + _, identity, "D") _    

or apply it to a list of As ... Ds directly:

List(A(42, "foo"), B(3.1415d), C("bar"), D).
  map(Foo.elim(_ + _, "" + _, identity, "D")).
  foreach(println)

This would output

42foo
3.1415
bar
D

If this isn't worth it, just use case classes with usual pattern matching.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.