functional programming with php7

46
Functional Programming with PHP 7

Upload: sergio-rafael-siqueira

Post on 21-Feb-2017

105 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Functional programming with php7

Functional Programming with PHP 7

Page 2: Functional programming with php7

About mehttp://sergiors.com

Don’t worry be happy and follow me ✌

Page 3: Functional programming with php7

What we will learn?

Page 4: Functional programming with php7

Functional Programming concepts, jargons and a lot of beautiful examples

that will be blow your mind.

Page 5: Functional programming with php7

And where I can use it? Can I apply it on a daily

basis?

Page 6: Functional programming with php7

In your data, business logic, etc… Of course!

Page 7: Functional programming with php7

https://speakerdeck.com/marcelgsantos/programacao-funcional-

em-php-saia-da-zona-de-conforto

For a deeper knowledge

Page 8: Functional programming with php7

Let’s go to the party!

Page 9: Functional programming with php7

Lambda or Anonymous function

Page 10: Functional programming with php7

$foo = function () {};

Page 11: Functional programming with php7

Closure

Page 12: Functional programming with php7

$bar = function () use ($fuzz) {}

It has access to external scope

Page 13: Functional programming with php7

Higher-order functions

Page 14: Functional programming with php7

Takes one or more functions as arguments and returns a function as its result.

Page 15: Functional programming with php7

Currying

Page 16: Functional programming with php7

Currying is converting a single function of n arguments into n functions with a single

argument each.

f(x, y, z) -> f(x)(y)(z)

Page 17: Functional programming with php7

function has($x){ return function (array $xss) use ($x) { return isset($xss[$x]); };}

$hasName = has('name');$hasName(['name' => 'Sérgio']); //=> true$hasName(['yearsOld' => 26]); //=> false

has('lastName')(['lastName' => 'Siqueira']); //=> true

Page 18: Functional programming with php7

Currying vs Partial Application

Page 19: Functional programming with php7

Partial Application, what?

Page 20: Functional programming with php7

function has(...$args){ return partial(function (array $xss, $x) { return isset($xss[$x]); })(...$args);}

$hasName = has('name');$hasName(['name' => 'Sérgio']); //=> true$hasName(['yearsOld' => 26]); //=> false

has('lastName')(['lastName' => 'Siqueira']); //=> true

Page 21: Functional programming with php7

function has(...$args){ return partial(function (array $xss, $x) { return isset($xss[$x]); })(...$args);}

$hasName = has('name');$hasName(['name' => 'Sérgio']); //=> true$hasName(['yearsOld' => 26]); //=> false

has('lastName')(['lastName' => 'Siqueira']); //=> true

Page 22: Functional programming with php7

Tacit programming or point-free style

Page 23: Functional programming with php7

function has(...$args){ return partial(function (array $xss, $x) { return isset($xss[$x]); })(...$args);}

$hasName = has('name');$hasName(['name' => 'Sérgio']); //=> true$hasName(['yearsOld' => 26]); //=> false

has('lastName')(['lastName' => 'Siqueira']); //=> true

Page 24: Functional programming with php7

function partial(callable $fn, ...$args){ $arity = (new \ReflectionFunction($fn)) ->getNumberOfRequiredParameters();

return isset($args[$arity - 1]) ? $fn(...$args) : function (...$restArgs) use ($fn, $args) { return partial($fn, ...array_merge($args, $restArgs)); };}

Page 25: Functional programming with php7

function partial(callable $fn, ...$args){ $arity = (new \ReflectionFunction($fn)) ->getNumberOfRequiredParameters();

return isset($args[$arity - 1]) ? $fn(...$args) : function (...$restArgs) use ($fn, $args) { return partial($fn, ...array_merge($args, $restArgs)); };}

Page 26: Functional programming with php7

Arity: Number of arguments a function or operator takes.

Page 27: Functional programming with php7

function partial(callable $fn, ...$args){ $arity = (new \ReflectionFunction($fn)) ->getNumberOfRequiredParameters();

return isset($args[$arity - 1]) ? $fn(...$args) : function (...$restArgs) use ($fn, $args) { return partial($fn, ...array_merge($args, $restArgs)); };}

Page 28: Functional programming with php7

function partial(callable $fn, ...$args){ $arity = (new \ReflectionFunction($fn)) ->getNumberOfRequiredParameters();

return isset($args[$arity - 1]) ? $fn(...$args) : function (...$restArgs) use ($fn, $args) { return partial($fn, ...array_merge($args, $restArgs)); };}

Page 29: Functional programming with php7

Stop! Where I use it?

Page 30: Functional programming with php7

Okey! Let’s go to my prelude!

Page 31: Functional programming with php7

Remember, in PHP, array also is hashmap

Page 32: Functional programming with php7

public function validate($value, Constraint $constraint){ if (empty($value)) { return $value; }

$violation = function () use ($value, $constraint) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $value) ->addViolation(); };

return pipe( function ($name) { return preg_replace('/(\d|[^\s\w])/u', '', $name); }, function ($name) { return preg_replace('/[\n\t\r]/', ' ', $name);

Page 33: Functional programming with php7

function tail(array $xss){ return array_slice($xss, 1);}

Page 34: Functional programming with php7

function ifElse(callable $pred){ return function (callable $succfn) use ($pred) { return function (callable $failfn) use ($pred, $succfn) { return function ($x = null) use ($pred, $succfn, $failfn) { return $pred($x) ? $succfn($x) : $failfn($x); }; }; };}

Page 35: Functional programming with php7

function id($id){ return $id;}

Page 36: Functional programming with php7

function lt($x){ return function ($y) use ($x) { return $x < $y; };}

Page 37: Functional programming with php7

function pipe(callable ...$callbacks){ return function ($payload) use ($callbacks) { $rest = tail(func_get_args());

return array_reduce($callbacks, function ($payload, $callback) use ($rest) { return $callback(...array_merge([$payload], $rest)); }, $payload); };}

Page 38: Functional programming with php7

public function validate($value, Constraint $constraint){ if (empty($value)) { return $value; }

$violation = function () use ($value, $constraint) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $value) ->addViolation(); };

return pipe( function ($name) { return preg_replace('/(\d|[^\s\w])/u', '', $name); }, function ($name) { return preg_replace('/[\n\t\r]/', ' ', $name); }, function ($name) { return preg_replace('/\s(?=\s)/', ' ', $name); }, function ($name) { return preg_match_all('/\w{2,}/u', trim($name)); }, ifElse(lt(1))(id)($violation) )($value);}

Page 39: Functional programming with php7

Immutability

Page 40: Functional programming with php7

$validate = anyPass([ [Validator::phone(), 'validate'], [Validator::cpf(), 'validate'],]);$sanitize = ifElse($validate) (function ($subject) { return preg_replace('/\D+/', '', $subject); }) (id);

$user = $this->createQueryBuilder('u') ->where('u.email = :username') ->orWhere("JSONB_HGG(u.data, '{phones, mobile}') = :username") ->orWhere("JSONB_MGG(u.data, 'cpf') = :username") ->setParameter('username', $sanitize($username)) ->getQuery() ->getOneOrNullResult();

$throw = function () { throw new \UserNotFoundException();};

return $user === null ? $throw() : $user;

Page 41: Functional programming with php7

function anyPass(array $preds){ return function ($x) use ($preds) { return array_reduce($preds, function (bool $prev, callable $pred) use ($x) { return true === $prev ? $prev : $pred($x); }, false ); };}

Page 42: Functional programming with php7

$foo = anyPass([ function (array $x) { return isset($x['mobile']); }, function (array $x) { return isset($x['last_name']); }]);

$foo(['last_name' => 'Siqueira']); //=> true$foo(['lastName'] => 'Siqueira'); //=> false

Lack the last argument,

point-free style

Page 43: Functional programming with php7

$foo = anyPass([ has('mobile'), has(‘last_name')]);

$foo(['last_name' => 'Siqueira']); //=> true$foo(['lastName'] => 'Siqueira'); //=> false

Page 44: Functional programming with php7

public function getOwner(): UserInterface{ $data = pipe(filter(has('owner')), head, get) ($this->data['admins'] ?? []);

return new User( $data('id'), $data('name'), new Email($data('email')) );}

Page 45: Functional programming with php7

http://github.com/sergiors/prelude

Page 46: Functional programming with php7

Thank you! 🍻Twitter @serg1ors Github @sergiors http://sergiors.com