GithubHelp home page GithubHelp logo

rfp's Introduction

Rfp - Real functional php

This is working prototype of library that supports functional programming. It is inspired by ramda and this talk, under hood uses functional php library.

IMPORTANT

This library is only a working prototype. The most of code was generated, it has not any tests and the performance issues was ignored. So you can play with this library and enjoy functional programming in php, but you should not use it in your project! If you like this project, give a star - this will be a sign for me, this kind of library is welcome.

Differences

Rfp is based on functional php, there are few very important changes:

  • there are F::compose and F::pipe functions. F::pipe does the same as F::compose function, but with reversed function order, so it is more readable.
  • making $collection last function argument
  • all functions support autocurring
  • there are more primitives

F::compose and F::pipe allow to functions chaining. There is a simple example:

    $composedFunc = F::compose($func1, $func2);
    //is the same as
    $composedFunc = function($x) use($func1, $func2){
        return $func1($func2($x));
    };
    
    $pipedFunc = F::pipe($func1, $func2);
    //is the same as
    $pipedFunc = function($x) use($func1, $func2){
        return $func2($func1($x));//unlike "compose", $func1 is invoked as first
    };

Curry is an operation on function that allows you to create function with smaller number of arguments.

Classical example:

    $add = function($a, $b) { 
        return $a + $b; 
    };
    
    $add5 = curry($add, 5);//we have a function like: function($b) { return 5 + $b; }
    
    $add5(3);//5 + 3

Autocurring is that when function gets less arguments than it expects, it will invoke curry on itself.

Consequences

  • You can pass functions as values

        $map = F::map();
        //yes, $map is F::map() function
  • You can easily create your own functions thanks to autocurring

        $idExtractor = F::map(F::prop('id'));//second argument missing - autocurring
        $ids = $idExtractor($objects);
  • You can call every function in normal way - just pass all arguments:

        $ids = F::map(F::prop('id'), $objects);
  • You can easily create your own functions thanks to F::pipe

        $sumQuantity = F::pipe(
            F::map(F::prop('quantity')),
            F::sum()
        );
  • autocurring and pipe allows you to write code where functions and data are separated - thanks to that, code is more declarative and you can take advantage from function composition.

  • Usage of Closures minimalized to minimum

Examples

/**
 * example from @lstrojny's article about functional programming
 *
 * Task: calculate cart value
 */

$cart = array(
    array(
        'name'     => 'Item 1',
        'quantity' => 10,
        'price'    => 9.99,
    ),
    array(
        'name'     => 'Item 2',
        'quantity' => 3,
        'price'    => 5.99,
    )
);

//using functional php

$value = F\sum(
    F\zip(
        F\pluck($cart, 'price'),
        F\pluck($cart, 'quantity'),
        function($price, $quantity) {
            return $price * $quantity;
        }
    )
);

//using Rfp

$value = F::pipe(
    F::converge(
        F::zip(F::multiply()),
        F::pluck('price'),
        F::pluck('quantity')
    ),
    F::sum()
)->apply($cart);

//converge is a new primitive, simplified implementation:
function converge($then, $func1, $func2) {
    return function($x) use($then, $func1, $func2){
        return $then($func1($x), $func2($x));
    };
}

/**
 * We have an array of patients and we want to know percentage of female patients grouped by blood type.
 */

$patients = array(/*...*/);

//using functional php

$result = F\map(
    F\group(
        $patients,
        function(Patient $patient){
            return $patient->bloodType;
        }
    ),
    function(array $patientsByBloodType){
        list($femalesCount, $malesCount) = F\map(
            F\partition(
                $patientsByBloodType,
                function(Patient $patient) {
                    return $patient->sex === 'female';
                }
            ),
            function($patients){
                return count($patients);
            }
        );

        return $femalesCount / 
        	($femalesCount + $malesCount) * 100;
    }
);

//using Rfp

$percent = function($a, $b){
    return $a / ($a+$b) * 100;
};

$result = F::pipe(
    F::group(F::prop('bloodType')),
    F::map(F::pipe(
        F::partition(
            F::pipe(F::prop('sex'), F::eq('female'))
        ),
        F::map(F::unary('count')),
        F::apply($percent)
    ))
)->apply($patients);

//unary is a new primitive - wraps given function and passes only 1 argument to it
//apply is a new primitive - it acts as call_user_func_array

rfp's People

Contributors

maciej-sz avatar psliwa avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.