User Tools

Site Tools


groimp-platform:xl-lambda

XL Lambda function

Since the java version used in GroIMP does not yet support the java lambda functions, GroIMP comes with a set of own lambda functions. A Lambda function or anonymous function is a function that is not connected to an identifier and can be handled like a variable.

The XL implementation is mostly designed for mathematical or logical operations and follows a clear but strict syntax: For instance the mathematical expression f(x)=x*0.7 could be defined by this expresison: IntToFloat f = int x ⇒ float x*0.7;, This can then be use to evaluate the function for a given integer to return a float: f.evaluateFloat​(3).

This implementation is provided for any combination of the common data types (e.g. float, int, char, boolean, object) as well as for Void (in this case no input parameter is needed or no result is provided) A full list can be found int the javadoc.

In the following a very simple example shows one possible use case of these functions, providing different mathematical calculations for instance of the same module in one rule:

module A(float len, FloatToFloat calc) extends Sphere(0.1)
{
	{setShader(GREEN);}
}
 
FloatToFloat l = float x => float x*1.2;
FloatToFloat m = float x => float x*0.7;
 
protected void init ()
[
	Axiom ==> F(1) [RU(30) RH(90)A(0.5,l)] [RU(-30) RH(90)A(0.5,m)];
]
 
public void run ()
[
	A(x,calc) ==> F(x) [RU(30) RH(90) A(calc.evaluateFloat(x),calc)] [RU(-30) RH(90) A(calc.evaluateFloat(x),calc)];
]

custom rules

By using a Object function (eg. ObjectToFloat, BooleanToObject, ObjectToObject) the object can be more specifically defined in the function. For example the follwing lambda function will only work with node of the module A but can therefore also use attributes of this moduel:

ObjectToFloat getLen = A a => float a.len;

This works with module types and interfaces, for example the following code would let all Node implementing the Organ interface add one to the age.

public interface organ{
	public int age;
 
	public void setAge(int a);
	public int getAge();
 
}
public void ageing(){
	ObjectToVoid grow = organ o => void o.setAge(o.getAge()+1);
	grow.evaluateVoid((*organ*));
 
}

Generators

Moreover it is possible to create lambda functions that return series of values. These functions add the therm generator at the and for instance DoubleToDoubleGenerator. They can be used with XL queries:

public void test (){
  DoubleToDoubleGenerator f = double x => double* ((*A*)).len*x;
  println(f.evaluateDouble(3));
}

In-line Lambda functions

In RGG, for Java as well as XL blocks it is possible to combine several expressions in one expression, using brackets and separating them by comma. The expressions will then be executed in order from left to right, and the last one on the right defines the return value of the surrounding lambda expression.

An expression can be almost any feature of RGG:

  • Variable declaration
  • Variable assignment/change
  • XL context query
  • Java/RGG functions
  • Ternary conditional operator

Variable handling

A simple example for a in-line lambda is the combination of several mathematical steps in one expression would be the following, which sets the value if a to 6.

int a = (int i=1,i++,i*3);

The variable i stays in the scope of the lambda expression and can be used by the two following expressions but not outside of the brackets.

XL Context queries

XL context queries e.g. (*F*) (loop over all F) can be used either access a field of each of the queried nodes directly (e.g. (*F*).length) or to create query variables (e.g. (*f:F*)).

For example ((*f:F*),f.length/f.diameter) would loop over each F and return the ratio of length to diameter. The result can then be used the same way as (*F*).length, e.g. with the Analytical Operators.

It is also possible to create several query variables, here for the average change in length from one F to the next F:

float m =mean(((*f1:F > f2:F*),f2.length/f1.length));

This can be combined with any other expression, yet it is important to keep in mind that the expressions on the right of the context query are repeated for each found pattern! Therefore (int i=0,i++,(*F*),i*=2) and (int i=0,(*F*),i++,i*=2) would have different values, because in the first one i++ is only called once and in the second one its called for every F in the scene.

Ternary conditional operator

An Ternary conditional operator is in simple terms a inline if else expression, using the following syntax to write for instance: if x then b else c with a ? b : c. With a being a boolean condition and b and c being expressions.

groimp-platform/xl-lambda.txt · Last modified: 2025/01/24 08:12 by Tim