Skip to content

Instantly share code, notes, and snippets.

@mathiasverraes
Created December 9, 2014 19:40
Show Gist options
  • Save mathiasverraes/0ec97dcd2d237eb25187 to your computer and use it in GitHub Desktop.
Save mathiasverraes/0ec97dcd2d237eb25187 to your computer and use it in GitHub Desktop.
max($list, $function) in php
<?php
// test data
class Foo {
private $a;
private $b;
function __construct($a, $b)
{
$this->a = $a;
$this->b = $b;
}
public function getA() { return $this->a; }
public function getB() { return $this->b; }
}
$list = [
$foo1 = new Foo(2, "bar"),
$foo2 = new Foo(5, "baz"),
$foo3 = new Foo(1, "bam"),
];
// simple
$isGreater = function($carry, $item) {
return is_null($carry) || $item->getA() > $carry->getA() ? $item : $carry;
};
$maxOfList = array_reduce($list, $isGreater);
assert($maxOfList === $foo2);
// reusable max() function
$max = function($list, callable $extract) {
$compare = function($carry, $item) use($extract) {
return is_null($carry) || $extract($item) > $extract($carry) ? $item : $carry;
};
return array_reduce($list, $compare);
};
$extractA = function($x) { return $x->getA();};
assert($max($list, $extractA) === $foo2);
@texdc
Copy link

texdc commented Dec 11, 2014

Foo::maxA may not be encapsulated, but the data and logic related to Foo is. Public getters is a leaky interface, but are necessary when using global functions. Otherwise how can the logic be performed without access to the internals of an object? Therefore, a simple class method effectively encapsulates both data and logic for that particular class.

class PupilService
{
    public function findOldestIn(array $aListOfPupils)
    {
        $compareAge = function(Pupil $carry = null, Pupil $item) {
            return ($carry == null || $item->isOlderThan($carry)) ? $item : $carry;
        };
        return array_reduce($aListOfPupils, $compareAge);
    }
}

max_by(__, method(@getAge, [], __)) is not elegant - it's incoherent. Attempts to remove syntactical noise, verbosity, and ceremony should not sacrifice clarity.

edit: convert static method to service method

@texdc
Copy link

texdc commented Dec 12, 2014

Ok, in order to have a truly simple and reusable function, you want find_by, not max_by. See my fork.

class PupilService
{
    public function findOldestIn(array $aListOfPupils)
    {
        $pupilIsOlder = function(Pupil $pupilA, Pupil $pupilB) {
            return $pupilA->isOlderThan($pupilB);
        };
        return find_by($aListOfPupils, $pupilIsOlder);
    }
}

http://3v4l.org/6O94O

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment