Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/Ibsciss/php-functional

functional tools implementation in PHP
https://github.com/Ibsciss/php-functional

Last synced: about 2 months ago
JSON representation

functional tools implementation in PHP

Awesome Lists containing this project

README

        

# Php Functional

[![Join the chat at https://gitter.im/Ibsciss/php-functional](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Ibsciss/php-functional?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
[![Travis CI](https://travis-ci.org/Ibsciss/php-functional.svg?branch=master)](https://travis-ci.org/Ibsciss/php-functional)
[![Code Coverage](https://scrutinizer-ci.com/g/Ibsciss/php-functional/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/Ibsciss/php-functional/?branch=master)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Ibsciss/php-functional/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/Ibsciss/php-functional/?branch=master)
[![Build Status](https://scrutinizer-ci.com/g/Ibsciss/php-functional/badges/build.png?b=master)](https://scrutinizer-ci.com/g/Ibsciss/php-functional/build-status/master)

A collection of functions and classes to provide some nice functional tools for your projects, with a simple, **consistent** and well tested api.

Especially useful to build data processing algorithms in a breeze.

## Install

Via Composer

``` bash
$ composer require ibsciss/php-functionnal
```

## Usage

### Simple example

Imagine you want to compute the total VAT amount for october:

Instead of doing things like this:

```php
function compute_october_vat() {
$total_vat_amount = 0;
foreach ($invoices as $invoice) {
if ($invoice->due_date->format('m') == '10') {
$total_vat_amount += $invoice->amount * 0.2;
}
}
return $total_vat_amount;
}
```

Or, if you want to try with map / reduce functions:

```php
function compute_october_vat() {
return array_reduce(
array_map(
function($invoice) { return $invoice->amount * 0.2; },
array_filter( $invoices, function($invoice) { return $invoice->due_date->format('m') == '10'; } )
),
function($x, $y) { return $x + $y; }, 0);
}
```

You can now use a more fluent api:

```php
function compute_october_vat() {
return Fp\collection($invoices)
->filter( function($invoice) { return $invoice->due_date->format('m') == '10'; }; )
->map( function($invoice) { return $invoice->amount * 0.2; }; )
->add();
}
```

## Functional helper

### Compose

The compose function give you the ability to create a new functions from existing functions:

```
compose(f,g,h)(x) == f(g(h(x)))
```

A practical example:

```php
$plus_one = function($x) { return $x + 1; };
$square = function($x) { return pow($x, 2); };

$plus_one_and_square = Fp\compose($plus_one, $square);
$plus_one_and_square(2) //return 9
```

_Of course you can compose as much functions as you want._

### Pipelines functions

Pipelines functions are useful to apply transformations to collections, Martin Fowler wrote a [very good introduction (based on ruby)](http://martinfowler.com/articles/collection-pipeline/) about it.
On the same blog, you'll find another resource to learn [how to refactor your too many loops using pipeline](http://martinfowler.com/articles/refactoring-pipelines.html).

The `map`, `filter` and `reduce` functions are wrapper around the native php function, to understand why we have made them please see the [FAQ](#faq).

#### Map

Apply a function to each item of a collection to create a new array.

```php
//square each item of the collection
Fp\map(
function($x) {
return pow($x, 2); //square function
}, [1,2,3]
); //return [1,4,9,16]
```

#### Filter

Build an array composed with items that returns true when passed in the given callback.

```php
//return even values from the collection
Fp\filter(
function($x) {
return ($x % 2 == 0);
},
[1,2,3,4]
); //return [2,4]
```

#### Reduce

It makes an accumulation by passing each item to the given callback.
The callback returning value is returned for the next call (an init value is provided for the first call).

```php
//sum values of the collection
Fp\reduce(
function($carry, $item) {
return $carray + $item
},
[1,2,3,4],
0
); //return 10
```

#### Chaining

You can chain operations by using the `Fp\collection(collection)` function (don't forget to call `values()` to get the results):

```php
//squared even values from the given collection
Fp\collection([1,2,3,4])
->filter(
function($x) { return ($x % 2 == 0); }
)
->map(
function($x) { return pow($x, 2); }
)
->values();
```

### Collection transducers

With classical pipeline functions, you have to iterate the whole collection for each step of the transformation
and create an intermediate collection which is a massive waste in memory usage.

Moreover you can't really extract a step to use it in other contexts which is bad for code reuse.

To tackle these downsides of classic pipeline function, the functional world come with a nice solution: `tranducers`.

#### Mapping
like map

#### Filtering
like filter

### scalar transducer

Use with `single_result` terminal reducer.

#### First
return the first element

#### Max
return the max

### Aggregate reducer

#### Batching
Batch result

#### Enumerating
Create indexed tuples with results

### Terminal reducer

#### appending
append to an array

#### conjoining
immutable appending by merge

#### single_result
to get a scalar result instead of a collection

## FAQ

### Why not using directly array_\* (array_filter, array_map) functions ?

- To improve api consistency
- To be able to produce transducers if the iterable is omitted
- To be able to consume `Collection` objects.

## Change log

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

## Testing

``` bash
$ composer test
```

## Contributing

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

## Security

If you discover any security related issues, please email :author_email instead of using the issue tracker.

## Credits

- [Arnaud LEMAIRE](https://github.com/lilobase)
- [All Contributors](../../contributors)

## License

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.