patternphpMinor
Making PHP composable and look functional
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
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
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.