Graal Forums

Graal Forums (https://forums.graalonline.com/forums/index.php)
-   NPC Scripting (https://forums.graalonline.com/forums/forumdisplay.php?f=8)
-   -   Functions as parameters (https://forums.graalonline.com/forums/showthread.php?t=134269322)

Chompy 06-17-2014 11:34 PM

Functions as parameters
 
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 = {
    
123,
    
456,
    
789
  
};

  
this.double = function (x) {
    return 
x*2;
  };

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

  
temp.array = {
    
123,
    
456,
    
789
  
};

  
temp.test this.filter(temp.array, this.= 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.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.= 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.= 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)

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...hp?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...hp?t=134258232
(Would not recommend using this one in production because it doesn't GC at all and will leak memory like a sieve.)


All times are GMT +2. The time now is 03:34 AM.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.