Thread: Prelude
View Single Post
  #1  
Old 11-23-2010, 03:35 AM
WhiteDragon WhiteDragon is offline
Banned
Join Date: Feb 2007
Posts: 1,002
WhiteDragon is a splendid one to beholdWhiteDragon is a splendid one to beholdWhiteDragon is a splendid one to beholdWhiteDragon is a splendid one to beholdWhiteDragon is a splendid one to behold
Prelude

Here is a pack of useful functions that let you operate on arrays and integers

PHP Code:
//#CLIENTSIDE

function onCreated() {

  
/* MISCELLANEOUS FUNCTIONS */

  // Return whatever is passed in
  
this.id = function (temp.a) {
    return 
temp.a;
  };
  
  
// Return the first parameter and ignore the second.
  
this.const = function (temp.atemp.b) {
    return 
temp.a;
  };

  
// Combine two functions and return a new function which executes them in order.
  // i.e.,    compose(f, g)(x) = f(g(x))
  
this.compose = function (temp.f1temp.f2) {
    
temp.= function (temp.x) {
      
temp.f1 this.(@"freevars_"@temp).f1;
      
temp.f2 this.(@"freevars_"@temp).f2;
      return (@
temp.f1)((@temp.f2)(temp.x));
    };
    
this.(@"freevars_"@temp.f).f1 temp.f1;
    
this.(@"freevars_"@temp.f).f2 temp.f2;
    return 
temp.f;
  };
    
  
//  Flip the parameters of a function.
  //  flip(f)(x, y) = f(y,x)
  
this.flip = function (temp.f1) {
    
temp.= function (temp.atemp.b) {
      
temp.f1 this.(@"freevars_"@temp.f).f1;
      return (@
temp.f1)(temp.btemp.a);
    };
    
this.(@"freevars_"@temp.f).f1 temp.f1;

    return 
temp.f;
  };
  
  
// Until p(x) is true, x = f(x) every recursive step. Return the final x (after all the fs are applied).
  
this.until = function (temp.ptemp.ftemp.x) {
    if ((@
temp.p)(temp.x)) {
      return 
temp.x;
    } else {
      return (@
temp)(temp.ptemp.f, (@temp.f)(temp.p));
    }
  };

  
/* BOOLEAN OPERATIONS */

  // Just negates a boolean. Useful for composing.
  
this.not = function (temp.a) {
    return !
temp.a;
  };


  
/* NUMERIC OPERATIONS */

  // Negates a number.
  
this.negate = function (temp.a) {
    return -
temp.a;
  };

  
// Get the sign of a number.
  
this.signum = function (temp.a) {
    if (
temp.0) {
      return -
1;
    } else if (
temp.== 0) {
      return 
0;
    } else {
      return 
1;
    }
  };

  
// Return the remainder of an integer division.
  
this.rem = function(temp.atemp.n) {
    return 
temp.temp.n*int(temp.a/temp.n);
  };

  
// Subtract two numbers.
  
this.subtract = function (temp.atemp.b) {
    return 
temp.temp.a;
  };

  
// Checks if a number is even
  
this.even = function (temp.a) {
    
temp.temp.a/2;
    return 
int(temp.a) != temp.a;
  };

  
// Checks if a number is odd
  
this.odd this.compose(this.notthis.even);

  
// Returns the greatest positive integer that divides both x and y.
  
this.gcd = function (temp.xtemp.y) {
    
temp.gcd2 = function (temp.atemp.b) {
      if (
temp.== 0) {
        return 
temp.a;
      } else {
        return (@
temp)(temp.bthis.rem(temp.atemp.b));
      }
    };
    if (
temp.== && temp.== 0) {
      
// error
    
} else {
      return (@
temp.gcd2)(abs(temp.x), abs(temp.y));
    }
  };
  
  
// Returns the smallest integer that both x and y divide.
  
this.lcm = function (temp.xtemp.y) {
    if (
temp.== || temp.== 0) {
      return 
0;
    } else {
      return 
abs((temp./ (this.gcd(temp.xtemp.y))) * temp.y);
    }
  };
  

  
  
/* LIST OPERATIONS */

  // Take a function and a list. Return a new list that has that function applied across it.
  
this.map = function (temp.ftemp.a) {
    
temp.temp.a.size();
  
    
temp.= {};
    for (
temp.0temp.temp.stemp.i++) {
      
temp.b.insert(temp.i, (@temp.f)(temp.a[temp.i]));
    }
  
    return 
temp.b;
  };

  
// Take a function and a list. Return a list that only has elements where temp.f was True for them.
  
this.filter = function (temp.ftemp.a) {
    
temp.temp.a.size();

    
temp.= {};  
    for (
temp.0temp.temp.stemp.i++) {
      if ((@
temp.f)(temp.a[temp.i]) == true) {
        
temp.b.add(temp.a[temp.i]);
      }
    }
  
    return 
temp.b;
  };

  
// return the first element in a list.
  
this.head = function (temp.a) {
    return 
temp.a[0];
  };
  
  
// return the last element of the list.
  
this.last = function (temp.a) {
    return 
temp.a[temp.a.size()-1];
  };
  
  
// return everything but the first element in a list.
  
this.tail = function (temp.a) {
    return 
temp.a.subarray(1);
  };
  
  
// return everything but the last element in a list.
  
this.init = function (temp.a) {
    return 
temp.a.subarray(0temp.a.size()-2);
  };
  
  
// takes a list and returns a new list that in reverse.
  
this.reverse = function (temp.a) {
    
temp.aSize temp.a.size();
    
temp.= new [temp.aSize];
    for (
temp.0temp.temp.aSizetemp.i++) {
      
temp.b[temp.i] = temp.a[temp.aSize-1-temp.i];
    }
    return 
temp.b;
  };

  
// Takes a 2-parameter function, a value, and a list of values, and combines the array into a new value based on that function moving from the left to the right. 
  
this.foldl = function (temp.ftemp.inittemp.a) {
    
temp.temp.a.size();

    
temp.result temp.init;
  
    for (
temp.0temp.temp.stemp.i++) {
      
temp.result = (@temp.f)(temp.resulttemp.a[temp.i]);
    }
  
    return 
temp.result;
  };

  
// Same as foldl, but no default value (the list must not be empty in this case). 
  
this.foldl1 = function (temp.ftemp.a) {
    
temp.temp.a.size();

    
temp.result temp.a[0];
  
    for (
temp.1temp.temp.stemp.i++) {
      
temp.result = (@temp.f)(temp.resulttemp.a[temp.i]);
    }

    return 
temp.result;  
  };

  
// Same as foldl but starts from the right of the list and moves left.
  
this.foldr = function (temp.ftemp.inittemp.a) {
    
temp.temp.a.size();

    
temp.result temp.init;
  
    for (
temp.temp.s-1temp.>= 0temp.i--) {
      
temp.result = (@temp.f)(temp.a[temp.i], temp.result);
    }
  
    return 
temp.result;
  };

  
// same as foldr but with no default value (list must be non-empty).
  
this.foldr1 = function (temp.ftemp.a) {
    
temp.temp.a.size();

    
temp.result temp.a[temp.s-1];
  
    for (
temp.temp.s-2temp.>= 0temp.i--) {
      
temp.result = (@temp.f)(temp.a[temp.i], temp.result);
    }

    return 
temp.result;  
  };



  
/* sublists */
  
  // takes the first temp.num values from a list
  
this.takee = function (temp.numtemp.a) {
    return 
temp.a.subarray(0temp.num);
  };
  
  
// drops the first temp.num values from a list
  
this.drop = function (temp.numtemp.a) {
    return 
temp.a.subarray(temp.num);
  };
  
  
// splits a list into two parts at temp.num
  
this.splitAt = function (temp.numtemp.a) {
    return {
temp.a.subarray(0temp.num), temp.a.subarray(temp.num)};
  };
  
  
// keep taking elements from temp.xs until temp.p is false on that element.
  
this.takeWhile = function (temp.ptemp.xs) {
    
temp.xsSize temp.xs.size();
    
temp.= {};
    for (
temp.0temp.temp.xsSizetemp.i++) {
      if ((@
temp.p)(temp.xs[temp.i])) {
        
temp.n.add(temp.xs[temp.i]);
      } else {
        break;
      }
    }
    return 
temp.n;
  };

  
// keep dropping elements from temp.xs while temp.p is true on that element.
  
this.dropWhile = function (temp.ptemp.xs) {
    
temp.xsSize temp.xs.size();
    
temp.= {};
    for (
temp.0temp.temp.xsSizetemp.i++) {
      if (!(@
temp.p)(temp.xs[temp.i])) {
        break;
      }
    }
    for (
temp.temp.itemp.temp.xsSizetemp.x++) {
      
temp.n.add(temp.xs[temp.x]);
    }
    return 
temp.n;
  };

  
// splits an array into two based on the function temp.p. This is basically {takeWhile(p,xs), dropWhile(p,xs)}
  
this.span = function (temp.ptemp.xs) {
    
temp.xsSize temp.xs.size();
    
temp.= {};
    for (
temp.0temp.temp.xsSizetemp.i++) {
      if ((@
temp.p)(temp.xs[temp.i])) {
        
temp.n.add(temp.xs[temp.i]);
      } else {
        break;
      }
    }
    
temp.n2 = {};
    for (
temp.temp.itemp.temp.xsSizetemp.x++) {
      
temp.n2.add(temp.xs[temp.x]);
    }
    return {
temp.ntemp.n2};
  };
  
  
// span, but with a negated temp.p
  
this.break = function (temp.ptemp.xs) {
    return 
this.span(this.compose(this.nottemp.p), temp.xs);
  };

Put this in a class, e.g., prelude, then:
PHP Code:
temp.= new TStaticVar();
temp.p.join("prelude");

temp.= function (temp.x) { return temp.x*2; }
echo(
temp.p.map(temp.f, {1,2,3,4})); // returns {2,4,6,8} 
Inspired by the Haskell Prelude. Also note there is some more documentation/examples at that link for the functions I provided. (Also more functions that I haven't converted to GS yet.)
Reply With Quote