rossriley / php-scalar-objects

Experimental API for PHP Scalar Objects
70 stars 6 forks source link

Member method partial application #13

Open eborden opened 10 years ago

eborden commented 10 years ago

One of the nice elements of PHP's scalar functions being represented as functions instead of member methods is that they allow for partial application. This is less intuitive with member methods since the eventual callee needs to provide a context and possibly additional arguments.

Functional Example

//Right handed partial application
function right_partial = ($callable, ...$rightArgs) {
    return function (...$leftArgs) use ($callable, $rightArgs) {
        return call_user_func_array($callable, array_merge($leftArgs, $rightArgs));
    };
} 

$strings = ['asfd', 'sdfg', 'setw', 'uyts', 'ghjk'];

// Partial application
array_map(right_partial('str_pos', 's', 0), $strings); //[1, 0, 0, 3, false]

// Inline
array_map(function ($str) {
    return str_pos($str, 's', 0);
}, $strings); //[1, 0, 0, 3, false]

Object Example

For member methods a special arrow function needs to exist to support these declarative techniques:

//Left handed partial application
function arrow ($method, $leftArgs) {
    return function ($context, $rightArgs) use ($method, $leftArgs) {
        return call_user_func_array([$context, $method], array_merge($leftArgs, $rightArgs));
    }
}

// Partial application
$strings->map(arrow('indexOf', 's', 0)); //[1, 0, 0, 3, false]

// Inline 
$strings->map(function ($str) {
    return $str->indexOf('s', 0);
}); //[1, 0, 0, 3, false]

Sugar

It would be nice if this could be sugared and provided at the language level. Options:

$strings->map(_->indexOf('s', 0)); //[1, 0, 0, 3, false]
$strings->map($->indexOf('s', 0)); //[1, 0, 0, 3, false]