-1

hoping for your help! I'm doing a java project that reproduces the logo language and im capped as I can't find an elegant and not too complicated way to switch between different rules / instructions, the project focuses on advanced programming and the use of Stream () is suggested; Predicate (); Function (); BiFunction () ect etc this is the list of instructions that I have implemented but that I have no idea how to branch them, i take them as a String:

  1. FORWARD (int);
  2. BACKWARD (int);
  3. LEFT (int);
  4. RIGHT (int);
  5. CLEARSCREEN;
  6. HOME;
  7. PENUP;
  8. PENDOWN;
  9. SETPENCOLOR (int) (int) (int);
  10. SETFILLCOLOR (int) (int) (int);
  11. SETSCREENCOLOR (int) (int) (int);
  12. SETPENSIZE (int);
  13. RIPETI (int) [ (cmds) ];
    • Repeats the sequence of commands in the command list (cmds)

I have thought of an if () else () or a switch () but it does not seem very elegant

  • So you're writing an interpreter? A `switch` is common, especially if you parse instructions into bytecode first so they're easy to iterate over and switch on. – Peter Cordes Jun 27 '22 at 12:13
  • @PeterCordes yeah, kind of, but my prof doesn't like methods that contain 15+ lines of code, should be as clean as possible in order to pass the exam. I have this class called **Action** which has all methods implemented which do exactly what I need, I just don't know how to branch the code from a string that tells me "Forward 50 10 0" and i take "Forward" = my method and "50,10,0" = my parameters – anthony eleuteri Jun 27 '22 at 12:23
  • Each case in the switch should be a function call, or even make an array of function pointers (or a Java equivalent, perhaps polymorphism and calling a virtual `.doit()` method on each bytecode object.) – Peter Cordes Jun 27 '22 at 13:23
  • @PeterCordes i was looking for a supplier + factory methods but i dont really know ho to do it, i mean do i have to create 1 class for every rule that i have? and ho do i menage the repeat(int) [(comands)] – anthony eleuteri Jun 27 '22 at 13:28

1 Answers1

1

If a switch would work but you don't want the method to have too many lines, you could try using a map, either from String to method calls (for which you could use lambdas), or from Enum values to the same.

Map<String, Runnable> operations = Map.ofEntries(
    Map.entry("FORWARD", () -> action.forward()),
    Map.entry("BACKWARD", () -> action.backward(),
    // . . .
);

Or

Map<Instruction, Runnable> operations = Map.ofEntries(
    Map.entry(Instruction.FORWARD, action::forward),
    Map.entry(Instruction.BACKWARD, action::backward),
    // . . .
);

Note that in the second example I used method references for the calls to the Action object, which I'm assuming you have an instance of at this point.

The problem is, your instructions take different numbers of parameters, so that is really just a sketch of a solution. You'll have to figure out how to apply it to your use case. In particular, you haven't mentioned how the Action methods accept the parameters. I suppose each one takes 0, 1, or multiple parameters, depending on the instruction.

One thing you could do is parse each command into an Enum instance for that command, and any parameters into a separate object; maybe a List<Integer>. I don't know if you can modify the Action class to accept that list instead of the individual parameters. Or maybe modify it to take e.g. forward(int... params) and you could then pass an int[] of the parameters.

Hopefully this will at least give you some ideas that will get you unstuck.

David Conrad
  • 15,432
  • 2
  • 42
  • 54
  • im having some idead,but as you said, one of the problems I have to solve is that each method takes N inputs, and even repeat takes N times another command (I have already decided that I will solve the problem upstream by sorting it from the input string and then looping), the problem is also the fact that I cannot change the signature of the method, I have to take the values exactly as I have described them above, in the meantime I thank you for ideas, I will try to adapt them! I was also looking at how to implement a factory method and predicates but it seems like a really tough challenge – anthony eleuteri Jun 28 '22 at 16:23
  • @anthonyeleuteri One thing you could try, since you can't change the signature of the method, is to write a wrapper class that has more convenient methods and just passes them on as necessary: `myaction.forward(int... params) { action.forward(params[0]); }` But that's a bit ugly, unfortunately. – David Conrad Jun 28 '22 at 17:58