# React/Partial

Partial function application.

[![Build Status](https://secure.travis-ci.org/reactphp/partial.png?branch=master)](http://travis-ci.org/reactphp/partial) [![Code Climate](https://codeclimate.com/github/reactphp/partial/badges/gpa.svg)](https://codeclimate.com/github/reactphp/partial)

## Install

The recommended way to install react/partial is [through composer](http://getcomposer.org).

```JSON
{
    "require": {
        "react/partial": "~2.0"
    }
}
```

## Concept

> Partial application (or partial function application) refers to the process
> of fixing a number of arguments to a function, producing another function of
> smaller arity. Given a function `f:(X x Y x Z) -> N`, we might fix (or
> 'bind') the first argument, producing a function of type `f:(Y x Z) -> N`.
> Evaluation of this function might be represented as `f partial(2, 3)`.
> Note that the result of partial function application in this case is a
> function that takes two arguments.

Basically, what this allows you to do is pre-fill arguments of a function,
which is particularly useful if you don't have control over the function
caller.

Let's say you have an async operation which takes a callback. How about a file
download. The callback is called with a single argument: The contents of the
file. Let's also say that you have a function that you want to be called once
that file download completes. This function however needs to know an
additional piece of information: the filename.

```php
public function handleDownload($filename)
{
    $this->downloadFile($filename, ...);
}

public function downloadFile($filename, $callback)
{
    $contents = get the darn file asynchronously...
    $callback($contents);
}

public function processDownloadResult($filename, $contents)
{
    echo "The file $filename contained a shitload of stuff:\n";
    echo $contents;
}
```

The conventional approach to this problem is to wrap everything in a closure
like so:

```php
public function handleDownload($filename)
{
    $this->downloadFile($filename, function ($contents) use ($filename) {
        $this->processDownloadResult($filename, $contents);
    });
}
```

This is not too bad, especially with PHP 5.4, but with 5.3 you need to do the
annoying `$that = $this` dance, and in general it's a lot of verbose
boilerplate that you don't really want to litter your code with.

This is where partial application can help. Since we want to pre-fill an
argument to the function that will be called, we just call `bind`, which will
insert it to the left of the arguments list. The return value of `bind` is a
new function which takes one `$content` argument.

```php
use function React\Partial\bind;

public function handleDownload($filename)
{
    $this->downloadFile($filename, bind([$this, 'processDownloadResult'], $filename));
}
```

Partialing is dependency injection for functions! How awesome is that?

## Examples

### bind

```php
use function React\Partial\bind;

$add = function ($a, $b) {
    return $a + $b;
};

$addOne = bind($add, 1);

echo sprintf("%d\n", $addOne(5));
// outputs 6
```

### bind_right

```php
use function React\Partial\bind_right;

$div = function ($a, $b, $c) {
    return $a / $b / $c;
};

$divMore = bind_right($div, 20, 10);

echo sprintf("%F\n", $divMore(100)); // 100 / 20 / 10
// outputs 0.5
```

### placeholder

It is possible to use the `…` function (there is an alias called
`placeholder`) to skip some arguments when partially applying.

This allows you to pre-define arguments on the right, and have the left ones
bound at call time.

This example skips the first argument and sets the second and third arguments
to `0` and `1` respectively. The result is a function that returns the first
character of a string.

**Note:** Usually your IDE should help but accessing the "…"-character
(HORIZONTAL ELLIPSIS, U+2026) differs on various platforms.

 - Windows: `ALT + 0133`
 - Mac: `ALT + ;` or `ALT + .`
 - Linux: `AltGr + .`

```php
use function React\Partial\bind;
use function React\Partial\…;

$firstChar = bind('substr', …(), 0, 1);
$mapped = array_map($firstChar, array('foo', 'bar', 'baz'));

var_dump($mapped);
// outputs ['f', 'b', 'b']
```

## Tests

To run the test suite, you need PHPUnit.

    $ phpunit

## License

MIT, see LICENSE.
