stereos
stereos

Reputation: 321

How to build a function on the fly in java?

I'm parsing a text file that is being mapped to some java code like such:

public void eval(Node arg)
    {
        if(arg.data.equals("rand"))
        {
            moveRandomly();
        }
        else if(arg.data.equals("home"))
        {
            goHome();
        }
            else if(arg.data.equals("iffood"))
    {
        ifFoodHere(arg.left, arg.right);
    }//snip..

This is going to need to be re-evaluated about a thousand times and I'd rather not have to traverse the whole thing every time. Is there any way to make this traversal once and then have it be a function that is called every other time?

Upvotes: 2

Views: 1999

Answers (3)

nicerobot
nicerobot

Reputation: 9235

If you know all the arguments/commands you can expect, i might do it like this:

enum Args {
  home, rand, iffood;

  private Method method;

  private Args () {
    try {
      this.method = Commands.class.getMethod(this.name(), Node.class);
    } catch (final Exception e) {}
  }
  public void invoke (final Node args)
    throws IllegalArgumentException, IllegalAccessException,
      InvocationTargetException {
    this.method.invoke(null, args);
  }
  public static Args valueOf (final Node arg) {
    return valueOf(arg.data);
  }
  public static void eval (final Node arg)
    throws IllegalArgumentException, IllegalAccessException,
      InvocationTargetException {
    valueOf(arg).invoke(arg);
  }
}

Command implementations are:

class Commands {    
  public static void home (final Node arg) {
    goHome(); // Call the implementation
    // or simply make these bodies the implementations.
  }
  public static void iffood (final Node arg) {
    ifFoodHere(arg.left, arg.right);
  }    
  public static void rand (final Node arg) {
    moveRandom();
  }
  //...
}

your eval() then becomes, simply:

try {
  Args.eval(arg);
} catch (IllegalArgumentException e) {
  // Handle unknown arg.data
}

Upvotes: 1

Joel
Joel

Reputation: 16655

You could make a Map of Runnables:

Map<String, Runnable> methods = new HashMap<String, Runnable>();
methods.put("rand", new Runnable() 
{
    public void run()
    {
        moveRandomly();
    }
});
...

then in your method

public void eval(Node arg)
{
    Runnable command = methods.get(arg.data);
    command.run();
}

Upvotes: 3

lexicore
lexicore

Reputation: 43651

Create an anonymous inner class.

Something like:

public Callable<Void> eval(Node arg)
{
  if(arg.data.equals("rand"))
  {
    return new Callable<Void>{ public Void call() { moveRandomly(); return null; } };
  }
  ...
}

Callable<Void> f = eval(a);
f.call();

Upvotes: 2

Related Questions