Skip to content

Instantly share code, notes, and snippets.

@masterfermin02
Last active December 22, 2017 21:51
Show Gist options
  • Save masterfermin02/cf345906183ac3a62fae4c5af49ca45b to your computer and use it in GitHub Desktop.
Save masterfermin02/cf345906183ac3a62fae4c5af49ca45b to your computer and use it in GitHub Desktop.
Usando programacion funcional en php
<?php
/**
* This is a implementantion in PHP of primary application logic for our Functional Programming blog example
* See related blog series at: https://masterfermin02.wordpress.com/tag/functional-programming/
* Version: 1.0
*/
// Access the `obj` using the property `prop`
function get_prop($obj, $prop)
{
if ( is_callable( $prop ) ) {
$key = call_user_func( $prop, $obj);
} elseif ( is_object( $obj ) && isset( $obj->{ $prop } ) ) {
$key = $obj->{ $prop };
} elseif ( isset( $obj[ $prop ] ) ) {
$key = $obj[ $prop ];
} else {
$key = $prop;
}
return $key;
}
function flip($fn) {
return function() use($fn){
$args = array_reverse(func_get_args());
return call_user_func_array($fn, $args);
};
}
function curry_left($callable)
{
$outerArguments = func_get_args();
array_shift($outerArguments);
return function() use ($callable, $outerArguments) {
return call_user_func_array($callable, array_merge($outerArguments, func_get_args()));
};
}
function curry_right($callable)
{
$outerArguments = func_get_args();
array_shift($outerArguments);
return function() use ($callable, $outerArguments) {
return call_user_func_array($callable, array_merge(func_get_args(), $outerArguments));
};
}
// Given a list of objects, return a list of the values
// for property 'prop' in each object
function pluck($list, $prop) {
return call_user_func(mapWith(getWith($prop)),$list);
}
// Filter `list` using the predicate function `fn`
function filter($list, $fn) {
return array_filter($list,$fn);
}
// Returns an object which groups objects in `list` by property `prop`. If
// `prop` is a function, will group the objects in list using the string returned
// by passing each obj through `prop` function.
function group($list, $prop) {
return array_reduce($list,function($grouped, $item) use($prop) {
$key = get_prop($item,$prop);
$grouped[$key][] = $item;
return $grouped;
}, []);
}
// Returns a new list by applying the function `fn` to each item
// in `list`
function map($list, $fn) {
return array_map($fn,$list);
}
function walk($list, $fn){
array_walk($list, $fn);
}
function reduce($list, $fn)
{
return array_reduce($list,$fn);
}
// Returns a new object which is the result of mapping
// each *own* `property` of `obj` through function `fn`
function mapObject($obj, $fn) {
$keys = is_array($obj) ? array_keys($obj) : get_object_vars($obj);
return array_reduce($keys,function($res,$key) use($obj,$fn){
$res[$key] = call_user_func_array( $fn, [$key, get_prop($obj,$key)]);
return $res;
},[]);
}
// Return new list as combination of the two lists passed
// The second list can be a function which will be passed each item
// from the first list and should return an array to combine against for that
// item. If either argument is not a list, it will be treated as a list.
//
// Ex., pair([a,b], [c,d]) => [[a,c],[a,d],[b,c],[b,d]]
function pair($list, $listFn) {
is_array($list) || ($list = [$list]);
(is_callable($listFn) || is_array($listFn)) || ($listFn = [$listFn]);
return call_user_func(flatMapWith(function($itemLeft) use($listFn) {
return call_user_func(mapWith(function($itemRight) use($itemLeft) {
return [$itemLeft, $itemRight];
}),is_callable($listFn) ? call_user_func( $listFn, $itemLeft ) : $listFn);
}),$list);
}
// Sort a list using comparator function `fn`,
// returns new array (shallow copy) in sorted order.
function _sort($list, $fn) {
usort($list, $fn);
return $list;
}
// Return a copy of the array 'list' flattened by one level, ie [[1,2],[3,4]] = [1,2,3,4]
function flatten($list) {
return array_reduce($list,function($items,$item){
return is_array($item) ? array_merge($items,$item) : $item;
},[]);
}
// Return a flattened list which is the result of passing each
// item in `list` thorugh the function `fn`
function flatMap($list, $fn) {
return flatten(map($list, $fn));
}
// Takes a binary comparison function
// and returns a version that adhere's to the Array#sort
// API of return -1, 0 or 1 for sorting.
function comparator($fn) {
return function($a,$b) use($fn){
if(call_user_func($fn,$a,$b)) return -1;
if(call_user_func($fn,$b,$a)) return 1;
return 0;
};
}
function getWith($fn)
{
return curry_right('get_prop',$fn);
}
function filterWith($fn)
{
return curry_right('filter',$fn);
}
function mapWith($fn)
{
return curry_right('map',$fn);
}
function groupBy($fn)
{
return curry_right('group',$fn);
}
function mapObjectWith($fn)
{
return curry_right('mapObject',$fn);
}
function flatMapWith($fn)
{
return curry_right('flatMap',$fn);
}
function pluckWith($fn)
{
return curry_right('pluck',$fn);
}
function pairWith($fn)
{
return curry_right('pair',$fn);
}
function sortBy($fn)
{
return curry_right('_sort',$fn);
}
function reduceWith($fn)
{
return curry_right('reduce',$fn);
}
function firstWith($fn)
{
return curry_right('first',$fn);
}
// Similar to Ramda's useWith(fn,...) which allows you to supply
// a function `fn`, along with one or more transform functions. When
// the returned function is called, it will each argument passed to `fn`
// using the correlating transform function - if there are more arguments
// than transform functions, those arguments will be passed as is.
function useWith($fn /*, txfn, ... */) {
$transforms = func_get_args();
array_shift($transforms);
$_transform = function($args) use($transforms) {
return array_map(function($arg,$i) use($transforms) {
return $transforms[$i]($arg);
},$args,array_keys($args));
};
return function() use($_transform,$transforms,$fn) {
$args = func_get_args();
$transformsLen = count($transforms);
$targs = array_slice($args,0,$transformsLen);
$remaining = array_slice($args,$transformsLen);
return call_user_func_array($fn, array_merge(call_user_func($_transform,$targs), $remaining));
};
}
// Return the first / last element matching a predicate
function first(array $array, $test) {
foreach($array as $v)
if(call_user_func($test,$v))
return $v;
return null;
}
// Return true if at least one element matches the predicate
function any($array, $test) {
foreach($array as $v)
if(call_user_func( $test,$v))
return true;
return false;
}
// Return true if all elements match the predicate
function all($array, $test) {
foreach($array as $v)
if(! call_user_func( $test,$v))
return false;
return true;
}
function last(array $array, $test) {
return first(array_reverse($array), $test);
}
function compose() {
$args = func_get_args();
$fn = array_shift($args);
$gn = array_shift($args);
$fog = $gn ? function() use($fn,$gn) { return call_user_func($fn,call_user_func_array($gn,func_get_args())); }
: $fn;
return count($args) > 0 ? call_user_func_array('compose', array_merge([$fog],$args)) : $fog;
}
function pipeline(){
return flip('compose');
}
// Simple comparison for '>='
function greaterThanOrEqual($a, $b) {
return $a >= $b;
}
function greaterThanOrEqualTo($to){
return curry_right('greaterThanOrEqual',$to);
}
function lessThan($a,$b) { return $a < $b; }
function greaterThan($a,$b) { return $a > $b; }
function equal($a,$b) { return $a == $b; }
function equalTo($to){ return curry_right('equal',$to); }
function setVal($a,$b)
{
$a = $b;
return $a;
}
function setValTo($to){
return curry_right('setVal',$to);
}
//$pipeline = flip('compose');
/*function compose(callable ...$functions)
{
$initial = array_shift($functions);
return array_reduce($functions, function ($f, $g) {
return function (...$args) use ($f, $g) {
return $f($g(...$args));
};
}, $initial);
}*/
/*function pipeline(callable ...$functions)
{
return compose(...array_reverse($functions));
}*/
// Right curried versions of the above functions, which
// allow us to create partially applied versions of each
// and use within a `compose()` or `sequence()` call
/*var getWith = rightCurry(get),
filterWith = rightCurry(filter),
mapWith = rightCurry(map),
groupBy = rightCurry(group),
mapObjectWith = rightCurry(mapObject),
flatMapWith = rightCurry(flatMap),
pluckWith = rightCurry(pluck),
pairWith = rightCurry(pair),
sortBy = rightCurry(sort);*/
<?php
/*
* Archivo usando en el articulo : https://masterfermin02.wordpress.com/2013/01/19/hola/
* author : Fermin Perdomo
*/
$data = json_decode('[
{
"id": 1,
"value1": 5,
"value2": 10
},
{
"id": 2,
"value1": 50,
"value2": 100
},
{
"id": 1,
"value1": 1,
"value2": 2
},
{
"id": 2,
"value1": 15,
"value2": 20
},
{
"id": 3,
"value1": 15,
"value2": 20
}
]');
include 'functional.php';
require 'vendor/autoload.php';
use League\Pipeline\Pipeline;
function trace($label){
return function($val) use($label) {
echo $label;
echo '\n';
print_r($val);
return $val;
};
}
/*
* @prop : mixed
* return : int;
* description : resive prop of the obj as an argument an return an useWith function
*/
function sumProp($prop){
return useWith('array_sum', pluckWith($prop));
}
function sumGroupRecord($prop,$list)
{
return [
'id' => $prop,
'value1' => sumProp('value1')($list),
'value2' => sumProp('value2')($list)
];
}
function groupById($list)
{
return groupBy(getWith('id'))($list);
}
$pipeLine = (new Pipeline)
->pipe('groupById')
->pipe(mapObjectWith('sumGroupRecord'));
$finalProcess = $pipeLine->process($data);
print_r($finalProcess);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment