Have you ever wondered if you could pass functions as parameters, and how that could help you sometimes? Well, I tried I guess.
What could you use functions as parameters for? You could pass on execution logic for said function when a certain thing happens in the logic above it. (functions like map,filter,find,each from other languages, or sorting algorithms)
Lets see.. first, lets make an example:
You have an array of numbers from 1 to 9. Your task is to create a function which doubles all array values. Preferably passing the doubling rule as a function to the array iterator.
PHP Code:
function onCreated() {
temp.array = {
1, 2, 3,
4, 5, 6,
7, 8, 9
};
this.double = function (x) {
return x*2;
};
this.filter = function (array, f) {
temp.r = {};
for(temp.i:array) {
temp.check = f(temp.i);
if(temp.check) temp.r.add(temp.check);
}
return temp.r;
};
temp.test = this.filter(temp.array, this.double);
echo(temp.test);
// above won't work, gives:
// Script: Function f not found
temp.test = this.filter(temp.array, function(x) {
return x*2;
});
// the above will actually give you a lot of errors like
// unexpected token, missing semicolon etc
}
You'll notice at first, Graal doesn't really fully support anonymous functions or passing on functions assigned to a variable. So how does one do it in Graal? Oddly enough, there's a weird workaround:
PHP Code:
function onCreated() {
this.filter = function (array, f) {
temp.r = {};
for(temp.i:array) {
temp.check = f(temp.i);
if(temp.check) temp.r.add(temp.check);
}
return temp.r;
};
temp.array = {
1, 2, 3,
4, 5, 6,
7, 8, 9
};
temp.test = this.filter(temp.array, this.f = function(x) {
return x*2;
});
echo(temp.test);
// 2,4,6,8,10,12,14,16,18
// you can actually even do this:
this.double = function (x) {
return x*2;
};
temp.test = this.filter(temp.array, this.f = this.double);
echo(temp.test);
// 2,4,6,8,10,12,14,16,18
}
Do you see it yet? There's a meaning behind using
this.f at these instances:
temp.test = this.filter(temp.array, this.f = function(x) {
return x*2;
});
temp.test = this.filter(temp.array, this.f = this.double);
Wait, no, this is actually just a mayor workaround
PHP Code:
function onCreated() {
this.each = function (list, f) {
for(temp.i=0;i<list.size();i++) f(list[i],i,list);
};
// md5 each element and salt with iterator count,
// and print 6 first letters
this.each(temp.array, this.f = function(e,i,array) {
temp.str = md5(e+i);
echo(temp.str.substring(0,6));
});
// works printing:
// 6bb61e
// cfcd20
}
If ones does ONE change:
PHP Code:
function onCreated() {
this.each = function (list, ff) {
for(temp.i=0;i<list.size();i++) ff(list[i],i,list);
};
// md5 each element and salt with iterator count,
// and print 6 first letters
this.each(temp.array, this.f = function(e,i,array) {
temp.str = md5(e+i);
echo(temp.str.substring(0,6));
});
// works printing:
// Script: Function ff not found
}
The only way for this to work, is if you name all your function parameters as f and only use f when accessing said function parameters inside the function logic, naming must be consistent for it to be of any use, and current state makes it a hazzle.
All it does is actually setting this.f to the function in the running script, making it "kinda global" in that script. This in returns allows use of
this.f and/or
f inside the functions as well, as they all inherit
this, and they point to the variable
this.f which was set during calling of the function. All an illusion kind of.
I wish Graal had support for proper anonymous functions. (PS: I used
filter deliberately)