Function as argument of another function


#1

Hi everyone,

I’m trying to pass a function as an argument of another function but can’t figure out how…

I’ve found plenty of infos on solution for Java 8 but sadly we can’t use those solution with processing if I get it correctly.

Then I’ve found infos on the callable interface but not enough to be able to implement it.

Is there someone that could give me a hand or point me to a decent link?

Here a small example of what I would like to do:

void setup() {
  MyVector vec = new MyVector(5, 12);
  vec.applyFunction(myFunction); // Vec will now be [10, 24]
}

float myFunction(float val) {
  return 2 * val;
}


class MyVector() {
  float[] values; 
  
  MyVector(float a, float b) {
    values = new float[2];
    values[0] = a;
    values[1] = b;
  }
  
  void applyFunction(function f) {
    values[0] = f(values[0]);
    values[1] = f(values[1]);
  }
}

#2

What you are looking for, functions that are variables, are called lambda expressions. The problem is that they were introduced only in Java 8, and, as far as I know, Processing uses older versions of Java, so you are out of luck with this idea.

Maybe there’s some hacky cool way to implement it - maybe you could just make up new classes for every function, and then juggle them around in a weird way to do hacky things, and each one of these classes has a f(float a, float b) type function, but I can’t think of such, at least not right now, and I don’t even know if it’s possible even that way.

Edit: here’s even complete real code of your example:


void setup(){
  MyVector vec = new MyVector(5, 12);
  vec.applyFunction(myFunction);
}

interface MyCoolInterface{
  float operation(float a,float b);
}

MyCoolInterface myFunction = (a,b) -> a*b;

class MyVector {
  float[] values; 
  
  MyVector(float a, float b) {
    values = new float[2];
    values[0] = a;
    values[1] = b;
  }
  
  void applyFunction(MyCoolInterface f) {
    values[0] = f.operation(values[0],2);
    values[1] = f.operation(values[1],2);
  }
}

If you paste it into Processing, however, it would show no errors, except a message talking about Java 8 pointing to the definition of myFunction, which is this:
Lambda expressions are only allowed at source level 1.8 or above

If you are interested, here’s a long thread on older forum with people talking about Processing switching to Java 8: https://forum.processing.org/two/discussion/comment/123676/


#3

It’s not really hacky. Anonymous classes were added in Java 1.1 precisely to support a form of functional programming in exactly this way.

MyCoolInterface myFunction = new MyCoolInterface() {
  public float operation(float a,float b) {
    return a * b;
  }
};

Or you can just use that as a method argument rather than assigning to a variable. All a bit clunky though. Lambdas were added as a cleaner and better performing alternative.


#4

I’ve wet my feet a little on the Java package java.util.function by instantiating a Predicate and passing it as an argument at these 2 old sketch links below: :crazy_face:

  1. Forum.Processing.org/two/discussion/21761/querying-arraylist#Item_2
  2. Forum.Processing.org/two/discussion/22823/how-to-implement-this-method#Item_2

Of course it’s not even close to an actual lambda -> syntax. But it’s as far as we can go under the PDE. :roll_eyes:


#5

Thanks everyone, the following is working great for me:

interface Function {
  float applyFunction(float a);
}

Function myFunction = new Function() {
  public float applyFunction(float a) {
    return 2 * a;
  }
};


void setup() {
  MyVector vec = new MyVector(5, 12);
  vec.display();
  vec.applyFunction(myFunction);
  vec.display();
}




class MyVector {
  float[] values; 

  MyVector(float a, float b) {
    values = new float[2];
    values[0] = a;
    values[1] = b;
  }

  void applyFunction(Function f) {
    values[0] = f.applyFunction(values[0]);
    values[1] = f.applyFunction(values[1]);
  }

  void display() {
    println(values[0], values[1]);
  }
}