HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

Making PHP composable and look functional

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
composablephplookfunctionalandmaking

Problem

I've found myself on numerous occasions needing to with large text-files, where joining this on that, and filtering this out on arbitrary conditions.

The first couple of times, this turned into a loop in a loop in a loop mess which was indented more times than I care to either remember or admit.

More recently, I've attempted to make something that looks and behaves more "functional". Below is the basic class and a simple example.

I'm primarily concerned with extensibility. I'm not sure the approach I use will lend itself to extensibility in the future. I though, for example, about trying to stream results to disc, and I'm not sure that's doable at all without a fundamental change. Similarly it would be useful to add a simple ->not() for negating a filter, which I also don't see easily doable here.

A secondary concern is performance. PHP is perhaps not the best choice for a functional style. I'm guessing the performance of all these function calls isn't fantastic. Anything obvious I can do to improve it? If "real" performance is a requirement, the obvious suggestion might just to be to not use PHP, but if there are cheap ways to stretch this further, it would be nice.

Code:

```
class Functional {
protected $result;
protected $extra_data;

public function __construct($array = NULL) {
$this->result = $array;
}

public function reduce($callback, $i = NULL) {
if ($i === NULL) {
$i = $this->result;
}

$result = array_reduce($i, $callback);
$this->result = $result;
return $this;
}

public function walk($callback, $i = NULL) {
if ($i === NULL) {
$i = $this->result;
}

array_walk($i, $callback);
$this->result = $i;
return $this;
}

public function filter($callback, $i = NULL) {
if ($i === NULL) {
$i = $this->result;
}

$this->result = array_filter($i, $callback);
return $this;
}

public function result() {
return $this->result;
}

public function gather($callback

Solution

I propose you a more compact version with code duplication removal:

You can compact all of your call with an apply method, as shown in the following code:

result = $array;
    }

    protected function apply($fn, $callback, $value)
    {
        $input = (is_null($value)) ? $this->result : $value;
        call_user_func($fn, $input, $callback);
        return $this;
    }

    public function reduce($callback, $i = NULL)
    {
        return $this->apply('array_reduce', $callback, $i);
    }

    public function walk($callback, $i = NULL)
    {
        return $this->apply('array_walk', $callback, $i);
    }

    public function filter($callback, $i = NULL)
    {
        return $this->apply('array_filter', $callback, $i);
    }

    public function result()
    {
        return $this->result;
    }

    public function gather($callback, $key)
    {
        $this->extra[$key] = $callback($this->result);
        return $this;
    }

    public function extra($key)
    {
        return $this->extra[$key];
    }
}

Code Snippets

<?php

class Functional
{
    protected $result;
    protected $extra_data;

    public function __construct($array = NULL)
    {
        $this->result = $array;
    }

    protected function apply($fn, $callback, $value)
    {
        $input = (is_null($value)) ? $this->result : $value;
        call_user_func($fn, $input, $callback);
        return $this;
    }

    public function reduce($callback, $i = NULL)
    {
        return $this->apply('array_reduce', $callback, $i);
    }

    public function walk($callback, $i = NULL)
    {
        return $this->apply('array_walk', $callback, $i);
    }

    public function filter($callback, $i = NULL)
    {
        return $this->apply('array_filter', $callback, $i);
    }

    public function result()
    {
        return $this->result;
    }

    public function gather($callback, $key)
    {
        $this->extra[$key] = $callback($this->result);
        return $this;
    }

    public function extra($key)
    {
        return $this->extra[$key];
    }
}

Context

StackExchange Code Review Q#72026, answer score: 2

Revisions (0)

No revisions yet.