0

I can't seem to find anything on google for this and I'm not sure it's possible. What I want to do, is pass a line of Java code as an argument to a method. Google only turns up results for passing cmd line arguments to methods, but I want to pass an actual line of code.

Basically I want to pass methodA to methodB except methodA isn't a method, but a line of code. Below is a full example of passing a method to a method using reflection.

public class Relation<T> {

protected Set<Pair<T,T>> pairs = null;

public Relation() {
    this.pairs = new LinkedHashSet<Pair<T,T>>();
}

    /* Next 2 methods are methods for sending methods to methods useing java.lang.reflect.Method */
    public Method getMethod(String name) {
        try {   return Relation.class.getDeclaredMethod(name);
        } catch (Exception e) {} 
        return null;
    }

    public boolean execute(Method method, Object... params) {
        try {   return (Boolean) method.invoke(this, params);
        } catch (Exception e) {}
        return false;
    }

    /* The method I reuse several times so I just put methods inside of it */   
    public boolean pairsTFIterator(Method method)  {
        for(Pair<T,T> x : pairs) {
            boolean bool = false;
            for(Pair<T,T> y : pairs) {
                if(execute(method, x,y))    
                    bool = true; break;
            }
            if(!bool) return false;
        }
        return true;
    }

    /* To be replaced by the line of code*/   
    public static <T> boolean isSymmetricPairs(Pair<T,T> a, Pair<T,T> b) {
        return a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false;
    }

    /* Method that calls others */
    public boolean isSymmetric() {
        return pairsTFIterator(getMethod("isSymmetricPairs"));
    }
}

The above works fine and all, but I want to take it a step further and just forego methods like the "isSymmetricPairs" method by just putting that methods logic line directly in the "pairsTFIterator", like so:

public boolean isReflexive() {  
    return  baseSetTFIterator(
            a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false
    );
}

I'm pretty sure this is impossible, but if there is someway to do it, that would be great.

Derek Ziemba
  • 2,467
  • 22
  • 22
  • No, this is not possible directly. You can parse the line and generate corresponding code though. Some expression languages do that. – Sotirios Delimanolis Mar 05 '14 at 03:09
  • This is Java. The idiomatic way to do this (until [Java 8 and lambdas](http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)) is to create an interface and anonymously implement it, exactly as you would with any other event-like idiom in Java. – Kirk Woll Mar 05 '14 at 03:39
  • I'm not quite understanding your specifications here. Is refelection a requirement, or can you some how use a v8 Lambda or (pre-8) Functor to encapsulate what you want? A Functor is a "function" but a line of code can obviously be encapsulated into one...assuming you're not attempting to write code "on the fly." I just wrote this yesterday: http://stackoverflow.com/questions/7369460/help-with-understanding-a-function-object-or-functor-in-java/22163940#22163940 . If I *am* understanding you, this answer (which is really a full-fledged blog post) should be helpful. – aliteralmind Mar 05 '14 at 03:39

2 Answers2

1

It sounds like what you are looking for are "first-class functions". Some languages treat functions just like a variable, in the sense that you can assign them to variables and pass them as arguments to other functions. Java 8 will be introducing the concept of lambda expressions which will support this type of functionality.

Also there are other JVM languages that provide this already, including Scala and Groovy to name two of the more popular ones.

Just to give you a flavor of what it looks like, in Groovy you can execute arbitrary functions on each element of a collection by calling the each() method and passing it a closure (a function essentially).

def list = [1, 2, 3, 4]
def printer = { x -> println x } // defines a closure that takes one arg and prints it
list.each(printer) // prints out the elements

def sum = 0
def summer = { x -> sum += x } // defines a closure that takes one arg and adds it to the sum variable
list.each(summer)
println sum // should be 1 + 2 + 3 + 4
jeff
  • 4,325
  • 16
  • 27
1

Put you code in an anonymos inner class may satisfy your requirement:

    interface PairFilter<T>{
        boolean filter(Pair<T, T> a, Pair<T,T> b);
    }

And in you iterator method:

    public boolean pairsTFIterator(PairFilter filter) {
        for(Pair<T,T> x : pairs) {
            boolean bool = false;
            for(Pair<T,T> y : pairs) {
                if(filter.filter(x,y))    
                    bool = true; break;
                }
                if(!bool) return false;
        }
        return true;
    }

then call it:

    pairsTFIterator(new PairFilter<T>(){
        public boolean filter(Pair<T, T> a, Pair<T,T> b){
            return a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false;
        }
    });
Safrain
  • 294
  • 1
  • 5