PDA

View Full Version : Functions as parameters

Chompy
06-17-2014, 11:34 PM
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.

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);
}
return temp.r;
};

temp.test = this.filter(temp.array, this.double);
echo(temp.test);
// above won't work, gives:

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:

function onCreated() {
this.filter = function (array, f) {
temp.r = {};
for(temp.i:array) {
temp.check = f(temp.i);
}
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

function onCreated() {
this.each = function (list, f) {
for(temp.i=0;i<list.size();i++) f(list,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:

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:
}

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 [I]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)

WhiteDragon
06-18-2014, 03:05 PM
It's possible. You just need to cast the function to a string then call it. (@temp.f)(). Check out this: http://forums.graalonline.com/forums/showthread.php?t=134261142

And, if you'd like to see something far more evil (getting access to the environment the function was defined in within the function), check out this: http://forums.graalonline.com/forums/showthread.php?t=134258232
(Would not recommend using this one in production because it doesn't GC at all and will leak memory like a sieve.)