SlideShare a Scribd company logo
Witek Adamus
DocPlanner 2017, Warszawa
Why async
and
functional
programming
in PHP7 suck
and how to
get over it?
Who am I?
5 years of
imperative
programming
2 years of
functional
programming
Back to
PHP7
❏ WHY?
❏ What can functional programming bring to the table?
❏ WHAT?
❏ When language can be described as functional?
❏ PROBLEMS?
❏ Top sins of PHP
❏ SOLUTION?
Table of content
WHY?
❏ Higher quality?
❏ Speed / Scalability
❏ Less bugs
❏ Easy to reason about
❏ Predictability
WHY?
WHY?
Pros Cons
Efficiency ???
Entry threshold ???
Mathematical
description of
reality
???
WHY?
Pros Cons In result
Efficiency Efficiency Scalability / Quality
Entry threshold Entry threshold Let’s get the party
started
Mathematical
description of
reality
Mathematical
description of
reality
Shorter and more
descriptive code
WHY?
Pros Cons In result
Efficiency Efficiency Scalability / Quality
Entry threshold Entry threshold Let’s get the party
started
Mathematical
description of
reality
Mathematical
description of
reality
Shorter and more
descriptive code
INVEST AND WAIT
FOR A DIVIDEND
public function someMethodWithMisleadingName(
array $mysteriousInput){
$arr = [];
foreach ($mysteriousInput as $inp) {
if ($inp > 10) { $arr[] = $inp; }
}
$arrLeft = $arrRight = $arrCenter = [];
foreach ($arr as $elem) {
$bucket = $elem <=> 20;
if ($bucket < 0) { $arrLeft[] = $elem; }
if ($bucket == 0) { $arrCenter[] = $elem; }
if ($bucket > 0) { $arrRight[] = $elem;}
}
$countLeft = count($arrLeft);
$countCenter = count($arrCenter);
$countRight = count($arrRight);
return array_sum([$countLeft, $countCenter, $countRight]) / 3;
}
public function someMethodWithMisleadingName(
array $mysteriousInput) {
$arr = [];
foreach ($mysteriousInput as $inp) {
if ($inp > 10) { $arr[] = $inp; }
}
$arrLeft = $arrRight = $arrCenter = [];
foreach ($arr as $elem) {
$bucket = $elem <=> 20;
if ($bucket < 0) { $arrLeft[] = $elem; }
if ($bucket == 0) { $arrCenter[] = $elem; }
if ($bucket > 0) { $arrRight[] = $elem;}
}
$countLeft = count($arrLeft);
$countCenter = count($arrCenter);
$countRight = count($arrRight);
return array_sum(
[$countLeft, $countCenter, $countRight]
) / 3;
}
public function
someMethodWithMisleadingName(
ParallelListCollection $mysteriousInput) {
return $mysteriousInput
->filter(function ($elem) {
return $elem > 10;
})
->partition(function ($elem) {
return $elem <=> 20;
})
->map(function ($bucket) {
return $bucket->count();
})
->avg();
}
public function someMethodWithMisleadingName(
array $mysteriousInput) {
$arr = [];
foreach ($mysteriousInput as $inp) {
if ($inp > 10) { $arr[] = $inp; }
}
$arrLeft = $arrRight = $arrCenter = [];
foreach ($arr as $elem) {
$bucket = $elem <=> 20;
if ($bucket < 0) { $arrLeft[] = $elem; }
if ($bucket == 0) { $arrCenter[] = $elem; }
if ($bucket > 0) { $arrRight[] = $elem;}
}
$countLeft = count($arrLeft);
$countCenter = count($arrCenter);
$countRight = count($arrRight);
return array_sum(
[$countLeft, $countCenter, $countRight]
) / 3;
}
public function
someMethodWithMisleadingName(
ParallelListCollection $mysteriousInput) {
return $mysteriousInput
->filter(function ($elem) {
return $elem > 10;
})
->partition(function ($elem) {
return $elem <=> 20;
})
->map(function ($bucket) {
return $bucket->count();
})
->avg();
}
WHAT?
❏ Function is a first-class citizen
❏ Lambda Calculus
❏ Immutability
❏ No side effects
First-class citizen
❏ Can be stored in variable and data structures
❏ Can be passed as a parameter to procedure/functions
❏ Can be returned by procedures/functions
❏ Can be instantiated inline
❏ Has it’s own identity (name independent)
Lambda Calculus
ƛ(x) = z
Lambda Calculus
ƛ(x) = z
❏ Higher-order functions
❏ Currying
Lambda Calculus
ƛ(x) = z
❏ Higher-order functions
❏ Currying
SWITCH YOUR THINKING
FROM “HOW?” TO “WHAT?”
No side effects? Immutability?
:(
Functional vs Object oriented programming
?
Why async and functional programming in PHP7 suck and how to get overr it?
PHP7 is functional
…but is dirty and salty as well
What do I miss in PHP7 that Scala
luckily has?
❏ Immutability by default
❏ Objects cloning
❏ Options
❏ Either
❏ Future
❏ Parallel collections
❏ Tail recurrency
❏ Generic types
❏ Arrow functions
❏ Pattern matching / case classes
https://github.com/php-slang/php-slang
http://phpslang.io
# composer require php-slang/php-slang
Few rules to
make your
code
functional
Do not use
❏ reassignments
❏ if
❏ null
❏ for
❏ foreach
Quick pool
❏ Do you DDD?
Quick pool
❏ Do you DDD?
❏ Do you use setters?
Quick pool
❏ Do you DDD?
❏ Do you use setters?
“VALUE OBJECTS are completely immutable.”
Eric Evans
Do not use
❏ reassignments
$bigHouse = new Building(5);
$bigHouse = new Building(5);
$smallerHouse = $bigHouse->setFloors(2);
echo $bigHouse->getFloors();
echo $smallerHouse->getFloors();
$bigHouse = new Building(5);
$smallerHouse = $bigHouse->setFloors(2);
echo $bigHouse->getFloors(); //2
echo $smallerHouse->getFloors(); //2
class Building
{
protected $floors;
public function __construct(int $floors)
{
$this->setFloors($floors);
}
public function getFloors() : int
{
return $this->floors;
}
public function setFloors(int $floors) : Building
{
$this->floors = $floors;
return $this;
}
}
use PhpSlangUtilCopy;
class Building
{
use Copy;
protected $floors;
public function __construct(int $floors)
{
$this->floors = $floors;
}
public function getFloors() : int
{
return $this->floors;
}
public function withFloors(int $floors) : Building
{
return $this->copy('floors', $floors);
}
}
$bigHouse = new Building(5);
$smallerHouse = $bigHouse->withFloors(2);
echo $bigHouse->getFloors(); //5
echo $smallerHouse->getFloors(); //2
$bigHouse = new Building(5);
$smallerHouse = $bigHouse->withFloors(2);
echo $bigHouse->getFloors(); //5
echo $smallerHouse->getFloors(); //2
REFERENTIALTRANSPARENCY
Referential transparency
❏ f(x, y) = (x+y) * y
Referential transparency
❏ f(x, y) = (x+y) * y
x, y and a result can
be a function as well
Referential transparency
❏ f(x, y) = (x+y) * y
Eg.
❏ f(2, 4) = (2 + 4) * 4 = 8 * 4 = 32
❏ f(1, 8) = (1 + 8) * 8 = 9 * 8 = 72
Referential transparency
❏ f(x, y) = (x+y) * y
Eg.
❏ f(2, 4) = (2 + 4) * 4 = 8 * 4 = 32
❏ f(1, 8) = (1 + 8) * 8 = 9 * 8 = 72
i = 71;
ComputingService::_opCount++;
comps.push(new Tuple2(x, y));
Referential transparency
❏ f(x, y) = (x+y) * y
Eg.
❏ f(2, 4) = (2 + 4) * 4 = 8 * 4 = 32
❏ f(1, 8) = (1 + 8) * 8 = 9 * 8 = 72
i = 71;
ComputingService::_opCount++;
comps.push(new Tuple2(x, y));
Few rules to
make your
code
functional
Do not use
:) reassignments
❏ if
❏ null
❏ for
❏ foreach
Do not use
:) reassignments
❏ if
❏ null
❏ for
❏ foreach
?
Do not use
:) reassignments
❏ if
❏ null
❏ for
❏ foreach
Option
Option
Monad which may contain something or nothing
What is a monad?
What is a monad?
What is a monad?
What is a monad?
What is a monad?
map
What is a monad?
flatMap
What is a monad?
Option
Option
NoneSome
Option
Option
NoneSome
map(Closure $expression)
getOrElse($default)
map(Closure $expression)
getOrElse($default)
Option
Option
NoneSome
map(Closure $expression)
getOrElse($default)
map(Closure $expression)
getOrElse($default)
Some($expression($this->content)
$this->content
Option
Option
NoneSome
map(Closure $expression)
getOrElse($default)
map(Closure $expression)
getOrElse($default)
None
$default
public function findByEmail(string $email) : User
{
$user = $this->findOneBy(['email' => $email]);
if (!$user instanceof User) {
throw new NotFoundException("oh my");
}
return $user;
}
try {
return new Response(findByEmail($email), HTTP_OK);
} catch (NotFoundException $exception) {
return new Response([], HTTP_NOT_FOUND);
}
public function findByEmail(string $email) : User
{
$user = $this->findOneBy(['email' => $email]);
if (!$user instanceof User) {
throw new NotFoundException("oh my");
}
return $user;
}
try {
return new Response(findByEmail($email), HTTP_OK);
} catch (NotFoundException $exception) {
return new Response([], HTTP_NOT_FOUND);
}
public function findByEmail(string $email) : Option
{
return Option::of($this->findOneBy(['email' => $email]));
}
return findByEmail($email))
->map(function (User $user) {
return new Response($user, HTTP_OK);
})
->getOrElse(new Response('', HTTP_NOT_FOUND));
public function findByEmail(string $email) : User
{
$user = $this->findOneBy(['email' => $email]);
if (!$user instanceof User) {
throw new NotFoundException("oh my");
}
return $user;
}
try {
return new Response(findByEmail($email), HTTP_OK);
} catch (NotFoundException $exception) {
return new Response([], HTTP_NOT_FOUND);
}
public function findByEmail(string $email) : Option
{
return Option::of($this->findOneBy(['email' => $email]));
}
return findByEmail($email))
->map(function (User $user) {
return new Response($user, HTTP_OK);
})
->getOrElse(new Response('', HTTP_NOT_FOUND));
map
Option
How about nesting
public function findByEmail(string $email) : Option
{
return Option::of($this->findOneBy(['email' => $email]));
}
public function postalCode(string $email, PostalCode $default) : PostalCode
{
return findByEmail($email)
->map(function (User $user) {
return $user->getProfile()->getAdress()->getPostalCode();
})
->getOrElse($default);
}
public function postalCode(string $email, PostalCode $default) : PostalCode
{
return findByEmail($email);
->map(function (User $user) {
return $user->getProfile()->getAdress()->getPostalCode();
})
->getOrElse($default);
}
public function postalCode(string $email, PostalCode $default) : PostalCode
{
return findByEmail($email)
->flatMap(function (User $user) {
return $user->getProfile();
})
->flatMap(function (UserProfile $userProfile) {
return $userProfile->getAdress();
})
->flatMap(function (Adress $adress) {
return $adress->getPostalCode();
})
->getOrElse($default);
}
public function postalCode(string $email, PostalCode $default) : PostalCode
{
return findByEmail($email)
->flatMap(function (User $user) {
return $user->getProfile();
})
->flatMap(function (UserProfile $userProfile) {
return $userProfile->getAdress();
})
->flatMap(function (Adress $adress) {
return $adress->getPostalCode();
})
->getOrElse($default);
}
flatMap
Few rules to
make your
code
functional
Do not use
:) reassignments
:) if
:) null
❏ for
❏ foreach
Shortened notation for
anonymous functions
public function displayNameForUser(string $email) : string
{
return $this
->userRepository
->findByEmail($email)
->flatMap(function (User $user) {
return $user->getFirstName();
})
->getOrCall(function () use (string $email) : string {
return $this->getSomethingElseWith($email);
});
}
public function displayNameForUser(string $email) : string
{
return $this
->userRepository
->findByEmail($email)
->flatMap(function (User $user) {
return $user->getFirstName();
})
->getOrCall(function () use (string $email) : string {
return $this->getSomethingElseWith($email);
});
}
public displayNameForUser(string email) : string
userRepository
->findByEmail(email)
->flatMap(_->getFirstName)
->getOrCall(getSomethingElseWith(email))
:(
public def displayNameForUser(email : string) : string =
userRepository
.findByEmail(email)
.flatMap(_.getFirstName)
.getOrElse(_ => getSomethingElseWith(email))
:)
public function displayNameForUser(string $email) : string
{
return $this
->userRepository
->findByEmail($email)
->flatMap(Extract($user)->getFirstName())
->getOrCall(Extract($this)->getSomethingElseWith($email));
}
NYI
:)
Generic types
public function maybeSomething(string $email) : Option
{
...
}
/**
* @return Option<string>
*/
public function maybeSomething(string $email) : Option
{
...
}
https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md
:(
public function maybeSomething(string $email) : Option<string>
{
...
}
:o
public function maybeSomething(string $email) : Option<string>
{
...
}
❏ Version: 0.4.0
❏ Date: 2016-01-06
❏ Author:
❏ Ben Scholzen 'DASPRiD' mail@dasprids.de,
❏ Rasmus Schultz rasmus@mindplay.dk
❏ Status: Draft
❏ First Published at: http://wiki.php.net/rfc/generics
:(
public function maybeSomething(string $email) : Option<string>
{
...
}
WANT TO EARN EXTRA $1020 ?
https://www.bountysource.com/issues/20553561-add-generics-support
:~|
Syntax doesn’t matter
thinking does
Erlang guys
What do I miss in PHP7 that Scala
luckily has?
:/ Immutability by default
:) Objects cloning
:) Options
❏ Either
❏ Future
❏ Parallel collections
❏ Tail recurrency
:( Generic types
:( Arrow functions
❏ Pattern matching / case classes
Either
Either
Either
RightLeft
Either
Either
RightLeft
left(Closure $expr): Either
right(Closure $expr): Either
get()
left(Closure $expr): Either
right(Closure $expr): Either
get()
Either
Either
RightLeft
left(Closure $expr): Either
right(Closure $expr): Either
get()
left(Closure $expr): Either
right(Closure $expr): Either
get()
SEMANTICS!
What do I miss in PHP7 that Scala
luckily has?
:/ Immutability by default
:) Objects cloning
:) Options
:) Either
❏ Future
❏ Parallel collections
❏ Tail recurrency
:( Generic types
:( Arrow functions
❏ Pattern matching / case classes
Pattern Matching
Pattern matching
Result
Variant 1
Variant 2
Variant 3
Variant N
...
return (Match::of($someKindResult))
->match(
new Case(IvalidInput::class, new Response('', HTTP_BAD_REQUEST)),
new Case(NotFound::class, new Response('',HTTP_NOT_FOUND),
new Default(function () use ($someKindResult) {
return new Response($someKindResult, HTTP_OK);
})
);
What do I miss in PHP7 that Scala
luckily has?
:/ Immutability by default
:) Objects cloning
:) Options
:) Either
❏ Future
❏ Parallel collections
❏ Tail recurrency
:( Generic types
:( Arrow functions
:)/:( Pattern matching / case classes
Parallel collections
Parallel collections
Collection
N...3210
public function beautifulMultiplyOddsBy(
array $input, float $multiplication) : ListCollection
{
return (new ListCollection($input))
->filter(function ($number) {
return $number % 2 !== 0;
})
->map(function ($number) use ($multiplication) {
return $number * $multiplication;
});
}
public function accumulatedText(array $words) : string {
$text = '';
foreach ($words as $word) {
$text .= $word . ' ';
}
return $text;
}
public function accumulatedText(array $words) : string {
return (new ListCollection($words))
->fold('', function (string $acumulator, string $word) {
return $acumulator . $word . ' ';
});
}
(new ListCollection([1,2,3,4]))->tail(); //ListCollection([2,3,4])
(new ListCollection([1,2,3,4]))->every(2); //ListCollection([2,4])
(new ListCollection([1,2,3,4]))->groups(2);
ListCollection([
ListCollection([1,2]),
ListCollection([3,4]),
])
Few rules to
make your
code
functional
Do not use
:) reassignments
:) if
:) null
:) for
:) foreach
Parallelism vs Concurrency
Why async and functional programming in PHP7 suck and how to get overr it?
Why async and functional programming in PHP7 suck and how to get overr it?
Future
public function nonBlockingGet(string $id): Future
{
...
}
public function exampleAction(string $id1) : Response
{
return $this
->nonBlockingService
->nonBlockingGet($id)
->map(function (NonBlockingGetResult $output) {
return new Response($output);
})
->await();
}
public function nonBlockingGet(string $id): Future
{
...
}
public function exampleAction(string $id1) : Response
{
return $this
->nonBlockingService
->nonBlockingGet($id)
->map(function (NonBlockingGetResult $output) {
return new Response($output);
})
->await();
}
Future<NonBlockingGetResult>
NYI
public function nonBlockingGet(string $id): Future
{
...
}
public function exampleAction(string $id1) : Response
{
return $this
->nonBlockingService
->nonBlockingGet($id)
->map(function (NonBlockingGetResult $output) {
return new Response($output);
})
->await();
}
Future<NonBlockingGetResult>
NYI
Future<Response>
public function nonBlockingGet(string $id): Future
{
...
}
public function exampleAction(string $id1) : Response
{
return $this
->nonBlockingService
->nonBlockingGet($id)
->map(function (NonBlockingGetResult $output) {
return new Response($output);
})
->await();
}
Future<NonBlockingGetResult>
NYI
Future<Response>
Response
public function nonBlockingGet(string $id): Future
{
...
}
public function exampleAction(string $id1, string $id2, string $id3) : Response
{
return Future::all([
$this->nonBlockingService1->nonBlockingGet($id1),
$this->nonBlockingService2->nonBlockingGet($id2),
$this->nonBlockingService3->nonBlockingGet($id3),
])
->map(function ($output) {
return new Response($output);
})
->await();
}
NYI
Future & Parallel collections
use PhpSlangCollectionListCollection;
...
public function beautifulMultiplyBy(array $input, float $multiplication) : ListCollection
{
return (new ListCollection($input))
->map(function ($number) use ($multiplication) {
return $number * $multiplication;
});
}
use PhpSlangCollectionParallelListCollection;
...
public function beautifulMultiplyBy(array $input, float $multiplication) : ParallelListCollection
{
return (new ParallelListCollection($input))
->map(function ($number) use ($multiplication) {
return $number * $multiplication;
});
}
use PhpSlangCollectionListCollection;
...
public function asyncChainedComputationExample(array $input) : ListCollection
{
return (new ListCollection($input))
->map($this->transformationOne());
}
use PhpSlangCollectionParallelListCollection;
...
public function asyncChainedComputationExample(array $input) : ParallelListCollection
{
return (new ParallelListCollection($input))
->map($this->transformationOne());
}
use PhpSlangCollectionListCollection;
...
public function asyncChainedComputationExample(array $input) : ListCollection
{
return (new ListCollection($input))
->map($this->transformationOne());
}
use PhpSlangCollectionParallelListCollection;
...
public function asyncChainedComputationExample(array $input) : ParallelListCollection
{
return (new ParallelListCollection($input))
->map($this->transformationOne());
}
use PhpSlangCollectionParallelListCollection;
...
public function asyncChainedComputationExample(array $input) : ParallelListCollection
{
return (new ParallelListCollection($input))
->map($this->transformationOne());
}
CPU vs IO
use PhpSlangCollectionParallelListCollection;
...
public function asyncChainedComputationExample(array $input) : ParallelListCollection
{
return (new ParallelListCollection($input))
->map($this->transformationOne())
->map($this->transformationTwo())
->map($this->transformationThree();
}
use PhpSlangCollectionParallelListCollection;
...
public function asyncChainedComputationExample(array $input) : ParallelListCollection
{
return (new ParallelListCollection($input))
->map(function ($number) {
return new Some($number)
->map($this->transformationOne())
->map($this->transformationTwo())
->map($this->transformationThree()
->get();
});
}
use PhpSlangCollectionParallelListCollection;
…
public function asyncChainedComputationExample(array $input) : ParallelListCollection
{
return (new ParallelListCollection($input))
->map(function ($number) {
return new Some($number)
->map($this->transformationOne())
->map($this->transformationTwo())
->map($this->transformationThree()
->get();
});
}
What do I miss in PHP7 that Scala
luckily has?
:/ Immutability by default
:) Objects cloning
:) Options
:) Either
:/ Future
:) Parallel collections
❏ Tail recurrency
:( Generic types
:( Arrow functions
:)/:( Pattern matching / case classes
Tail recurrency
def fibonacci(index : Int) : Int =
index match {
case 0 | 1 => index
case _ => fibonacci(index - 1 ) + fibonacci(index - 2)
}
function fibonacci(int $index) : int
{
return in_array($index, [0, 1])
? $index
: fibonacci($index - 1) + fibonacci($index - 2);
}
def fibonacci(index : Int) : Int =
index match {
case 0 | 1 => index
case _ => fibonacci(index - 1 ) + fibonacci(index - 2)
}
function fibonacci(int $index) : int
{
return in_array($index, [0, 1])
? $index
: fibonacci($index - 1) + fibonacci($index - 2);
}
echo fibonacci(123123123123);
Fatal error: Maximum function nesting level of '...' reached, aborting!
ini_set('xdebug.max_nesting_level', 9999999);
?
def fibonacci(index: Int): Int = {
var a = 0
var b = 1
var i = 0
while (i < index) {
val c = a + b
a = b
b = c
i = i + 1
}
return a
}
function fibonacci(int $index) : int
{
$a = 0;
$b = 1;
$i = 0;
while ($i < $index) {
$c = $a + $b;
$a = $b;
$b = $c;
$i += 1;
}
return $a;
}
def recursiveFibonacci(n: Int, a:Int, b:Int): Int =
n match {
case 0 => a
case _ => recursiveFibonacci( n-1, b, a+b )
}
def fibonacci( n : Int) : Int =
recursiveFibonacci( n, 0, 1)
function recursiveFibonacci(int $n, int $a, int $b) {
return ($n == 0)
? $a
: recursiveFibonacci($n - 1, $b, $a + $b);
}
function fibonacci(int $n) : int
{
return recursiveFibonacci($n, 0, 1);
}
def fibonacci(index : Int) : Int =
index match {
case 0 | 1 => index
case _ => fibonacci(index - 1 ) + fibonacci(index - 2)
}
function fibonacci(int $index) : int
{
return in_array($index, [0, 1])
? $index
: fibonacci($index - 1) + fibonacci($index - 2);
}
@tailrec
def recursiveFibonacci(n: Int, a:Int, b:Int): Int =
n match {
case 0 => a
case _ => recursiveFibonacci( n-1, b, a+b )
}
def fibonacci( n : Int) : Int =
recursiveFibonacci( n, 0, 1)
function recursiveFibonacci(int $n, int $a, int $b) {
return ($n == 0)
? $a
: recursiveFibonacci($n - 1, $b, $a + $b);
}
function fibonacci(int $n) : int
{
return recursiveFibonacci($n, 0, 1);
}
:(
:)
Tail recurrency
Trampolines
Recurrency
Recurrency Trampoline
function recursiveFibonacci(int $n, int $a, int $b) {
return ($n == 0)
? $a
: recursiveFibonacci($n - 1, $b, $a + $b);
}
function fibonacci($n)
{
return recursiveFibonacci($n, 0, 1);
}
function recursiveFibonacci(int $n, int $a, int $b) {
return ($n == 0)
? new Done($a)
: new Bounce(function () use ($n, $b, $a) {
return recursiveFibonacci($n - 1, $b, $a + $b);
});
}
function fibonacci($n)
{
return (new Trampoline(function () use ($n) {
return recursiveFibonacci($n, 0, 1);
}))->run();
}
Recurrency Trampoline
What do I miss in PHP7 that Scala
luckily has?
:/ Immutability by default
:) Objects cloning
:) Options
:) Either
:/ Future
:) Parallel collections
:) Tail recurrency
:( Generic types
:( Arrow functions
:)/:( Pattern matching / case classes
Why async and functional programming in PHP7 suck and how to get overr it?
Conclusions
● Don’t be afraid of monads
● Care about transparency (especially referential)
● Learn Haskell, Clojure, Scala, F#, JavaScript -> TypeScript
Witek Adamus
witold.adamus@xsolve.pl
http://phpslang.io

More Related Content

What's hot (20)

Hive function-cheat-sheet
Hive function-cheat-sheet
Dr. Volkan OBAN
 
R Language Introduction
R Language Introduction
Khaled Al-Shamaa
 
R Refcard
R Refcard
Alexandre Gracioso
 
Data transformation-cheatsheet
Data transformation-cheatsheet
Dieudonne Nahigombeye
 
High-Performance Haskell
High-Performance Haskell
Johan Tibell
 
Data Analysis and Programming in R
Data Analysis and Programming in R
Eshwar Sai
 
Python programming : Standard Input and Output
Python programming : Standard Input and Output
Emertxe Information Technologies Pvt Ltd
 
Scala. Introduction to FP. Monads
Scala. Introduction to FP. Monads
Kirill Kozlov
 
Frp2016 3
Frp2016 3
Kirill Kozlov
 
Map, Reduce and Filter in Swift
Map, Reduce and Filter in Swift
Aleksandras Smirnovas
 
Data Structures In Scala
Data Structures In Scala
Knoldus Inc.
 
Data Analysis with R (combined slides)
Data Analysis with R (combined slides)
Guy Lebanon
 
R programming intro with examples
R programming intro with examples
Dennis
 
R programming language
R programming language
Alberto Minetti
 
Introduction to R Programming
Introduction to R Programming
izahn
 
R language
R language
LearningTech
 
Programming in R
Programming in R
Smruti Sarangi
 
Python crush course
Python crush course
Mohammed El Rafie Tarabay
 
Introduction to pandas
Introduction to pandas
Piyush rai
 
Data import-cheatsheet
Data import-cheatsheet
Dieudonne Nahigombeye
 

Similar to Why async and functional programming in PHP7 suck and how to get overr it? (20)

PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
XSolve
 
Banishing Loops with Functional Programming in PHP
Banishing Loops with Functional Programming in PHP
David Hayes
 
Being functional in PHP (PHPDay Italy 2016)
Being functional in PHP (PHPDay Italy 2016)
David de Boer
 
Elements of Functional Programming in PHP
Elements of Functional Programming in PHP
Jarek Jakubowski
 
Functional Programming In PHP I
Functional Programming In PHP I
Umut IŞIK
 
Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)
David de Boer
 
Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?
Nikita Popov
 
Functional Programming in PHP
Functional Programming in PHP
pwmosquito
 
Being functional in PHP
Being functional in PHP
David de Boer
 
XQuery - a technical overview
XQuery - a technical overview
Loren Cahlander
 
Functional programming with php7
Functional programming with php7
Sérgio Rafael Siqueira
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
Jeff Carouth
 
What's new, what's hot in PHP 5.3
What's new, what's hot in PHP 5.3
Jeremy Coates
 
Practical PHP 5.3
Practical PHP 5.3
Nate Abele
 
Object Oriented Programming in PHP
Object Oriented Programming in PHP
Lorna Mitchell
 
OOPs Concept
OOPs Concept
Mohammad Yousuf
 
PHP = PHunctional Programming
PHP = PHunctional Programming
Luis Atencio
 
Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"
Fwdays
 
Functional Programming in PHP
Functional Programming in PHP
Aurimas Niekis
 
Good functional programming is good programming
Good functional programming is good programming
kenbot
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
XSolve
 
Banishing Loops with Functional Programming in PHP
Banishing Loops with Functional Programming in PHP
David Hayes
 
Being functional in PHP (PHPDay Italy 2016)
Being functional in PHP (PHPDay Italy 2016)
David de Boer
 
Elements of Functional Programming in PHP
Elements of Functional Programming in PHP
Jarek Jakubowski
 
Functional Programming In PHP I
Functional Programming In PHP I
Umut IŞIK
 
Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)
David de Boer
 
Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?
Nikita Popov
 
Functional Programming in PHP
Functional Programming in PHP
pwmosquito
 
Being functional in PHP
Being functional in PHP
David de Boer
 
XQuery - a technical overview
XQuery - a technical overview
Loren Cahlander
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
Jeff Carouth
 
What's new, what's hot in PHP 5.3
What's new, what's hot in PHP 5.3
Jeremy Coates
 
Practical PHP 5.3
Practical PHP 5.3
Nate Abele
 
Object Oriented Programming in PHP
Object Oriented Programming in PHP
Lorna Mitchell
 
PHP = PHunctional Programming
PHP = PHunctional Programming
Luis Atencio
 
Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"
Fwdays
 
Functional Programming in PHP
Functional Programming in PHP
Aurimas Niekis
 
Good functional programming is good programming
Good functional programming is good programming
kenbot
 
Ad

Recently uploaded (20)

4th International Conference on Computer Science and Information Technology (...
4th International Conference on Computer Science and Information Technology (...
ijait
 
Water demand - Types , variations and WDS
Water demand - Types , variations and WDS
dhanashree78
 
Week 6- PC HARDWARE AND MAINTENANCE-THEORY.pptx
Week 6- PC HARDWARE AND MAINTENANCE-THEORY.pptx
dayananda54
 
TEA2016AAT 160 W TV application design example
TEA2016AAT 160 W TV application design example
ssuser1be9ce
 
Structural Design for Residential-to-Restaurant Conversion
Structural Design for Residential-to-Restaurant Conversion
DanielRoman285499
 
chemistry investigatory project for class 12
chemistry investigatory project for class 12
Susis10
 
NALCO Green Anode Plant,Compositions of CPC,Pitch
NALCO Green Anode Plant,Compositions of CPC,Pitch
arpitprachi123
 
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
João Esperancinha
 
Montreal Dreamin' 25 - Introduction to the MuleSoft AI Chain (MAC) Project
Montreal Dreamin' 25 - Introduction to the MuleSoft AI Chain (MAC) Project
Alexandra N. Martinez
 
Fundamentals of Digital Design_Class_12th April.pptx
Fundamentals of Digital Design_Class_12th April.pptx
drdebarshi1993
 
02 - Ethics & Professionalism - BEM, IEM, MySET.PPT
02 - Ethics & Professionalism - BEM, IEM, MySET.PPT
SharinAbGhani1
 
COMPOSITE COLUMN IN STEEL CONCRETE COMPOSITES.ppt
COMPOSITE COLUMN IN STEEL CONCRETE COMPOSITES.ppt
ravicivil
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-Glands & Lugs, Simplex...
362 Alec Data Center Solutions-Slysium Data Center-AUH-Glands & Lugs, Simplex...
djiceramil
 
The first edition of the AIAG-VDA FMEA.pptx
The first edition of the AIAG-VDA FMEA.pptx
Mayank Mathur
 
Engineering Mechanics Introduction and its Application
Engineering Mechanics Introduction and its Application
Sakthivel M
 
Great power lithium iron phosphate cells
Great power lithium iron phosphate cells
salmankhan835951
 
WIRELESS COMMUNICATION SECURITY AND IT’S PROTECTION METHODS
WIRELESS COMMUNICATION SECURITY AND IT’S PROTECTION METHODS
samueljackson3773
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-Adaptaflex.pdf
362 Alec Data Center Solutions-Slysium Data Center-AUH-Adaptaflex.pdf
djiceramil
 
3. What is the principles of Teamwork_Module_V1.0.ppt
3. What is the principles of Teamwork_Module_V1.0.ppt
engaash9
 
Blood bank management system project report.pdf
Blood bank management system project report.pdf
Kamal Acharya
 
4th International Conference on Computer Science and Information Technology (...
4th International Conference on Computer Science and Information Technology (...
ijait
 
Water demand - Types , variations and WDS
Water demand - Types , variations and WDS
dhanashree78
 
Week 6- PC HARDWARE AND MAINTENANCE-THEORY.pptx
Week 6- PC HARDWARE AND MAINTENANCE-THEORY.pptx
dayananda54
 
TEA2016AAT 160 W TV application design example
TEA2016AAT 160 W TV application design example
ssuser1be9ce
 
Structural Design for Residential-to-Restaurant Conversion
Structural Design for Residential-to-Restaurant Conversion
DanielRoman285499
 
chemistry investigatory project for class 12
chemistry investigatory project for class 12
Susis10
 
NALCO Green Anode Plant,Compositions of CPC,Pitch
NALCO Green Anode Plant,Compositions of CPC,Pitch
arpitprachi123
 
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
João Esperancinha
 
Montreal Dreamin' 25 - Introduction to the MuleSoft AI Chain (MAC) Project
Montreal Dreamin' 25 - Introduction to the MuleSoft AI Chain (MAC) Project
Alexandra N. Martinez
 
Fundamentals of Digital Design_Class_12th April.pptx
Fundamentals of Digital Design_Class_12th April.pptx
drdebarshi1993
 
02 - Ethics & Professionalism - BEM, IEM, MySET.PPT
02 - Ethics & Professionalism - BEM, IEM, MySET.PPT
SharinAbGhani1
 
COMPOSITE COLUMN IN STEEL CONCRETE COMPOSITES.ppt
COMPOSITE COLUMN IN STEEL CONCRETE COMPOSITES.ppt
ravicivil
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-Glands & Lugs, Simplex...
362 Alec Data Center Solutions-Slysium Data Center-AUH-Glands & Lugs, Simplex...
djiceramil
 
The first edition of the AIAG-VDA FMEA.pptx
The first edition of the AIAG-VDA FMEA.pptx
Mayank Mathur
 
Engineering Mechanics Introduction and its Application
Engineering Mechanics Introduction and its Application
Sakthivel M
 
Great power lithium iron phosphate cells
Great power lithium iron phosphate cells
salmankhan835951
 
WIRELESS COMMUNICATION SECURITY AND IT’S PROTECTION METHODS
WIRELESS COMMUNICATION SECURITY AND IT’S PROTECTION METHODS
samueljackson3773
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-Adaptaflex.pdf
362 Alec Data Center Solutions-Slysium Data Center-AUH-Adaptaflex.pdf
djiceramil
 
3. What is the principles of Teamwork_Module_V1.0.ppt
3. What is the principles of Teamwork_Module_V1.0.ppt
engaash9
 
Blood bank management system project report.pdf
Blood bank management system project report.pdf
Kamal Acharya
 
Ad

Why async and functional programming in PHP7 suck and how to get overr it?

  • 2. Why async and functional programming in PHP7 suck and how to get over it?
  • 4. 5 years of imperative programming 2 years of functional programming Back to PHP7
  • 5. ❏ WHY? ❏ What can functional programming bring to the table? ❏ WHAT? ❏ When language can be described as functional? ❏ PROBLEMS? ❏ Top sins of PHP ❏ SOLUTION? Table of content
  • 7. ❏ Higher quality? ❏ Speed / Scalability ❏ Less bugs ❏ Easy to reason about ❏ Predictability WHY?
  • 8. WHY? Pros Cons Efficiency ??? Entry threshold ??? Mathematical description of reality ???
  • 9. WHY? Pros Cons In result Efficiency Efficiency Scalability / Quality Entry threshold Entry threshold Let’s get the party started Mathematical description of reality Mathematical description of reality Shorter and more descriptive code
  • 10. WHY? Pros Cons In result Efficiency Efficiency Scalability / Quality Entry threshold Entry threshold Let’s get the party started Mathematical description of reality Mathematical description of reality Shorter and more descriptive code INVEST AND WAIT FOR A DIVIDEND
  • 11. public function someMethodWithMisleadingName( array $mysteriousInput){ $arr = []; foreach ($mysteriousInput as $inp) { if ($inp > 10) { $arr[] = $inp; } } $arrLeft = $arrRight = $arrCenter = []; foreach ($arr as $elem) { $bucket = $elem <=> 20; if ($bucket < 0) { $arrLeft[] = $elem; } if ($bucket == 0) { $arrCenter[] = $elem; } if ($bucket > 0) { $arrRight[] = $elem;} } $countLeft = count($arrLeft); $countCenter = count($arrCenter); $countRight = count($arrRight); return array_sum([$countLeft, $countCenter, $countRight]) / 3; }
  • 12. public function someMethodWithMisleadingName( array $mysteriousInput) { $arr = []; foreach ($mysteriousInput as $inp) { if ($inp > 10) { $arr[] = $inp; } } $arrLeft = $arrRight = $arrCenter = []; foreach ($arr as $elem) { $bucket = $elem <=> 20; if ($bucket < 0) { $arrLeft[] = $elem; } if ($bucket == 0) { $arrCenter[] = $elem; } if ($bucket > 0) { $arrRight[] = $elem;} } $countLeft = count($arrLeft); $countCenter = count($arrCenter); $countRight = count($arrRight); return array_sum( [$countLeft, $countCenter, $countRight] ) / 3; } public function someMethodWithMisleadingName( ParallelListCollection $mysteriousInput) { return $mysteriousInput ->filter(function ($elem) { return $elem > 10; }) ->partition(function ($elem) { return $elem <=> 20; }) ->map(function ($bucket) { return $bucket->count(); }) ->avg(); }
  • 13. public function someMethodWithMisleadingName( array $mysteriousInput) { $arr = []; foreach ($mysteriousInput as $inp) { if ($inp > 10) { $arr[] = $inp; } } $arrLeft = $arrRight = $arrCenter = []; foreach ($arr as $elem) { $bucket = $elem <=> 20; if ($bucket < 0) { $arrLeft[] = $elem; } if ($bucket == 0) { $arrCenter[] = $elem; } if ($bucket > 0) { $arrRight[] = $elem;} } $countLeft = count($arrLeft); $countCenter = count($arrCenter); $countRight = count($arrRight); return array_sum( [$countLeft, $countCenter, $countRight] ) / 3; } public function someMethodWithMisleadingName( ParallelListCollection $mysteriousInput) { return $mysteriousInput ->filter(function ($elem) { return $elem > 10; }) ->partition(function ($elem) { return $elem <=> 20; }) ->map(function ($bucket) { return $bucket->count(); }) ->avg(); }
  • 14. WHAT? ❏ Function is a first-class citizen ❏ Lambda Calculus ❏ Immutability ❏ No side effects
  • 15. First-class citizen ❏ Can be stored in variable and data structures ❏ Can be passed as a parameter to procedure/functions ❏ Can be returned by procedures/functions ❏ Can be instantiated inline ❏ Has it’s own identity (name independent)
  • 17. Lambda Calculus ƛ(x) = z ❏ Higher-order functions ❏ Currying
  • 18. Lambda Calculus ƛ(x) = z ❏ Higher-order functions ❏ Currying SWITCH YOUR THINKING FROM “HOW?” TO “WHAT?”
  • 19. No side effects? Immutability? :(
  • 20. Functional vs Object oriented programming ?
  • 22. PHP7 is functional …but is dirty and salty as well
  • 23. What do I miss in PHP7 that Scala luckily has?
  • 24. ❏ Immutability by default ❏ Objects cloning ❏ Options ❏ Either ❏ Future ❏ Parallel collections ❏ Tail recurrency ❏ Generic types ❏ Arrow functions ❏ Pattern matching / case classes
  • 26. Few rules to make your code functional
  • 27. Do not use ❏ reassignments ❏ if ❏ null ❏ for ❏ foreach
  • 28. Quick pool ❏ Do you DDD?
  • 29. Quick pool ❏ Do you DDD? ❏ Do you use setters?
  • 30. Quick pool ❏ Do you DDD? ❏ Do you use setters? “VALUE OBJECTS are completely immutable.” Eric Evans
  • 31. Do not use ❏ reassignments
  • 32. $bigHouse = new Building(5);
  • 33. $bigHouse = new Building(5); $smallerHouse = $bigHouse->setFloors(2); echo $bigHouse->getFloors(); echo $smallerHouse->getFloors();
  • 34. $bigHouse = new Building(5); $smallerHouse = $bigHouse->setFloors(2); echo $bigHouse->getFloors(); //2 echo $smallerHouse->getFloors(); //2
  • 35. class Building { protected $floors; public function __construct(int $floors) { $this->setFloors($floors); } public function getFloors() : int { return $this->floors; } public function setFloors(int $floors) : Building { $this->floors = $floors; return $this; } }
  • 36. use PhpSlangUtilCopy; class Building { use Copy; protected $floors; public function __construct(int $floors) { $this->floors = $floors; } public function getFloors() : int { return $this->floors; } public function withFloors(int $floors) : Building { return $this->copy('floors', $floors); } }
  • 37. $bigHouse = new Building(5); $smallerHouse = $bigHouse->withFloors(2); echo $bigHouse->getFloors(); //5 echo $smallerHouse->getFloors(); //2
  • 38. $bigHouse = new Building(5); $smallerHouse = $bigHouse->withFloors(2); echo $bigHouse->getFloors(); //5 echo $smallerHouse->getFloors(); //2 REFERENTIALTRANSPARENCY
  • 40. Referential transparency ❏ f(x, y) = (x+y) * y x, y and a result can be a function as well
  • 41. Referential transparency ❏ f(x, y) = (x+y) * y Eg. ❏ f(2, 4) = (2 + 4) * 4 = 8 * 4 = 32 ❏ f(1, 8) = (1 + 8) * 8 = 9 * 8 = 72
  • 42. Referential transparency ❏ f(x, y) = (x+y) * y Eg. ❏ f(2, 4) = (2 + 4) * 4 = 8 * 4 = 32 ❏ f(1, 8) = (1 + 8) * 8 = 9 * 8 = 72 i = 71; ComputingService::_opCount++; comps.push(new Tuple2(x, y));
  • 43. Referential transparency ❏ f(x, y) = (x+y) * y Eg. ❏ f(2, 4) = (2 + 4) * 4 = 8 * 4 = 32 ❏ f(1, 8) = (1 + 8) * 8 = 9 * 8 = 72 i = 71; ComputingService::_opCount++; comps.push(new Tuple2(x, y));
  • 44. Few rules to make your code functional
  • 45. Do not use :) reassignments ❏ if ❏ null ❏ for ❏ foreach
  • 46. Do not use :) reassignments ❏ if ❏ null ❏ for ❏ foreach ?
  • 47. Do not use :) reassignments ❏ if ❏ null ❏ for ❏ foreach Option
  • 48. Option Monad which may contain something or nothing
  • 49. What is a monad?
  • 50. What is a monad?
  • 51. What is a monad?
  • 52. What is a monad?
  • 53. What is a monad? map
  • 54. What is a monad? flatMap
  • 55. What is a monad?
  • 60. public function findByEmail(string $email) : User { $user = $this->findOneBy(['email' => $email]); if (!$user instanceof User) { throw new NotFoundException("oh my"); } return $user; } try { return new Response(findByEmail($email), HTTP_OK); } catch (NotFoundException $exception) { return new Response([], HTTP_NOT_FOUND); }
  • 61. public function findByEmail(string $email) : User { $user = $this->findOneBy(['email' => $email]); if (!$user instanceof User) { throw new NotFoundException("oh my"); } return $user; } try { return new Response(findByEmail($email), HTTP_OK); } catch (NotFoundException $exception) { return new Response([], HTTP_NOT_FOUND); } public function findByEmail(string $email) : Option { return Option::of($this->findOneBy(['email' => $email])); } return findByEmail($email)) ->map(function (User $user) { return new Response($user, HTTP_OK); }) ->getOrElse(new Response('', HTTP_NOT_FOUND));
  • 62. public function findByEmail(string $email) : User { $user = $this->findOneBy(['email' => $email]); if (!$user instanceof User) { throw new NotFoundException("oh my"); } return $user; } try { return new Response(findByEmail($email), HTTP_OK); } catch (NotFoundException $exception) { return new Response([], HTTP_NOT_FOUND); } public function findByEmail(string $email) : Option { return Option::of($this->findOneBy(['email' => $email])); } return findByEmail($email)) ->map(function (User $user) { return new Response($user, HTTP_OK); }) ->getOrElse(new Response('', HTTP_NOT_FOUND)); map
  • 64. public function findByEmail(string $email) : Option { return Option::of($this->findOneBy(['email' => $email])); } public function postalCode(string $email, PostalCode $default) : PostalCode { return findByEmail($email) ->map(function (User $user) { return $user->getProfile()->getAdress()->getPostalCode(); }) ->getOrElse($default); }
  • 65. public function postalCode(string $email, PostalCode $default) : PostalCode { return findByEmail($email); ->map(function (User $user) { return $user->getProfile()->getAdress()->getPostalCode(); }) ->getOrElse($default); }
  • 66. public function postalCode(string $email, PostalCode $default) : PostalCode { return findByEmail($email) ->flatMap(function (User $user) { return $user->getProfile(); }) ->flatMap(function (UserProfile $userProfile) { return $userProfile->getAdress(); }) ->flatMap(function (Adress $adress) { return $adress->getPostalCode(); }) ->getOrElse($default); }
  • 67. public function postalCode(string $email, PostalCode $default) : PostalCode { return findByEmail($email) ->flatMap(function (User $user) { return $user->getProfile(); }) ->flatMap(function (UserProfile $userProfile) { return $userProfile->getAdress(); }) ->flatMap(function (Adress $adress) { return $adress->getPostalCode(); }) ->getOrElse($default); } flatMap
  • 68. Few rules to make your code functional
  • 69. Do not use :) reassignments :) if :) null ❏ for ❏ foreach
  • 71. public function displayNameForUser(string $email) : string { return $this ->userRepository ->findByEmail($email) ->flatMap(function (User $user) { return $user->getFirstName(); }) ->getOrCall(function () use (string $email) : string { return $this->getSomethingElseWith($email); }); }
  • 72. public function displayNameForUser(string $email) : string { return $this ->userRepository ->findByEmail($email) ->flatMap(function (User $user) { return $user->getFirstName(); }) ->getOrCall(function () use (string $email) : string { return $this->getSomethingElseWith($email); }); }
  • 73. public displayNameForUser(string email) : string userRepository ->findByEmail(email) ->flatMap(_->getFirstName) ->getOrCall(getSomethingElseWith(email)) :(
  • 74. public def displayNameForUser(email : string) : string = userRepository .findByEmail(email) .flatMap(_.getFirstName) .getOrElse(_ => getSomethingElseWith(email)) :)
  • 75. public function displayNameForUser(string $email) : string { return $this ->userRepository ->findByEmail($email) ->flatMap(Extract($user)->getFirstName()) ->getOrCall(Extract($this)->getSomethingElseWith($email)); } NYI :)
  • 77. public function maybeSomething(string $email) : Option { ... }
  • 78. /** * @return Option<string> */ public function maybeSomething(string $email) : Option { ... } https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md :(
  • 79. public function maybeSomething(string $email) : Option<string> { ... } :o
  • 80. public function maybeSomething(string $email) : Option<string> { ... } ❏ Version: 0.4.0 ❏ Date: 2016-01-06 ❏ Author: ❏ Ben Scholzen 'DASPRiD' [email protected], ❏ Rasmus Schultz [email protected] ❏ Status: Draft ❏ First Published at: http://wiki.php.net/rfc/generics :(
  • 81. public function maybeSomething(string $email) : Option<string> { ... } WANT TO EARN EXTRA $1020 ? https://www.bountysource.com/issues/20553561-add-generics-support :~|
  • 83. What do I miss in PHP7 that Scala luckily has?
  • 84. :/ Immutability by default :) Objects cloning :) Options ❏ Either ❏ Future ❏ Parallel collections ❏ Tail recurrency :( Generic types :( Arrow functions ❏ Pattern matching / case classes
  • 87. Either Either RightLeft left(Closure $expr): Either right(Closure $expr): Either get() left(Closure $expr): Either right(Closure $expr): Either get()
  • 88. Either Either RightLeft left(Closure $expr): Either right(Closure $expr): Either get() left(Closure $expr): Either right(Closure $expr): Either get() SEMANTICS!
  • 89. What do I miss in PHP7 that Scala luckily has?
  • 90. :/ Immutability by default :) Objects cloning :) Options :) Either ❏ Future ❏ Parallel collections ❏ Tail recurrency :( Generic types :( Arrow functions ❏ Pattern matching / case classes
  • 92. Pattern matching Result Variant 1 Variant 2 Variant 3 Variant N ...
  • 93. return (Match::of($someKindResult)) ->match( new Case(IvalidInput::class, new Response('', HTTP_BAD_REQUEST)), new Case(NotFound::class, new Response('',HTTP_NOT_FOUND), new Default(function () use ($someKindResult) { return new Response($someKindResult, HTTP_OK); }) );
  • 94. What do I miss in PHP7 that Scala luckily has?
  • 95. :/ Immutability by default :) Objects cloning :) Options :) Either ❏ Future ❏ Parallel collections ❏ Tail recurrency :( Generic types :( Arrow functions :)/:( Pattern matching / case classes
  • 98. public function beautifulMultiplyOddsBy( array $input, float $multiplication) : ListCollection { return (new ListCollection($input)) ->filter(function ($number) { return $number % 2 !== 0; }) ->map(function ($number) use ($multiplication) { return $number * $multiplication; }); }
  • 99. public function accumulatedText(array $words) : string { $text = ''; foreach ($words as $word) { $text .= $word . ' '; } return $text; } public function accumulatedText(array $words) : string { return (new ListCollection($words)) ->fold('', function (string $acumulator, string $word) { return $acumulator . $word . ' '; }); }
  • 100. (new ListCollection([1,2,3,4]))->tail(); //ListCollection([2,3,4]) (new ListCollection([1,2,3,4]))->every(2); //ListCollection([2,4]) (new ListCollection([1,2,3,4]))->groups(2); ListCollection([ ListCollection([1,2]), ListCollection([3,4]), ])
  • 101. Few rules to make your code functional
  • 102. Do not use :) reassignments :) if :) null :) for :) foreach
  • 106. Future
  • 107. public function nonBlockingGet(string $id): Future { ... } public function exampleAction(string $id1) : Response { return $this ->nonBlockingService ->nonBlockingGet($id) ->map(function (NonBlockingGetResult $output) { return new Response($output); }) ->await(); }
  • 108. public function nonBlockingGet(string $id): Future { ... } public function exampleAction(string $id1) : Response { return $this ->nonBlockingService ->nonBlockingGet($id) ->map(function (NonBlockingGetResult $output) { return new Response($output); }) ->await(); } Future<NonBlockingGetResult> NYI
  • 109. public function nonBlockingGet(string $id): Future { ... } public function exampleAction(string $id1) : Response { return $this ->nonBlockingService ->nonBlockingGet($id) ->map(function (NonBlockingGetResult $output) { return new Response($output); }) ->await(); } Future<NonBlockingGetResult> NYI Future<Response>
  • 110. public function nonBlockingGet(string $id): Future { ... } public function exampleAction(string $id1) : Response { return $this ->nonBlockingService ->nonBlockingGet($id) ->map(function (NonBlockingGetResult $output) { return new Response($output); }) ->await(); } Future<NonBlockingGetResult> NYI Future<Response> Response
  • 111. public function nonBlockingGet(string $id): Future { ... } public function exampleAction(string $id1, string $id2, string $id3) : Response { return Future::all([ $this->nonBlockingService1->nonBlockingGet($id1), $this->nonBlockingService2->nonBlockingGet($id2), $this->nonBlockingService3->nonBlockingGet($id3), ]) ->map(function ($output) { return new Response($output); }) ->await(); } NYI
  • 112. Future & Parallel collections
  • 113. use PhpSlangCollectionListCollection; ... public function beautifulMultiplyBy(array $input, float $multiplication) : ListCollection { return (new ListCollection($input)) ->map(function ($number) use ($multiplication) { return $number * $multiplication; }); }
  • 114. use PhpSlangCollectionParallelListCollection; ... public function beautifulMultiplyBy(array $input, float $multiplication) : ParallelListCollection { return (new ParallelListCollection($input)) ->map(function ($number) use ($multiplication) { return $number * $multiplication; }); }
  • 115. use PhpSlangCollectionListCollection; ... public function asyncChainedComputationExample(array $input) : ListCollection { return (new ListCollection($input)) ->map($this->transformationOne()); } use PhpSlangCollectionParallelListCollection; ... public function asyncChainedComputationExample(array $input) : ParallelListCollection { return (new ParallelListCollection($input)) ->map($this->transformationOne()); }
  • 116. use PhpSlangCollectionListCollection; ... public function asyncChainedComputationExample(array $input) : ListCollection { return (new ListCollection($input)) ->map($this->transformationOne()); } use PhpSlangCollectionParallelListCollection; ... public function asyncChainedComputationExample(array $input) : ParallelListCollection { return (new ParallelListCollection($input)) ->map($this->transformationOne()); }
  • 117. use PhpSlangCollectionParallelListCollection; ... public function asyncChainedComputationExample(array $input) : ParallelListCollection { return (new ParallelListCollection($input)) ->map($this->transformationOne()); } CPU vs IO
  • 118. use PhpSlangCollectionParallelListCollection; ... public function asyncChainedComputationExample(array $input) : ParallelListCollection { return (new ParallelListCollection($input)) ->map($this->transformationOne()) ->map($this->transformationTwo()) ->map($this->transformationThree(); }
  • 119. use PhpSlangCollectionParallelListCollection; ... public function asyncChainedComputationExample(array $input) : ParallelListCollection { return (new ParallelListCollection($input)) ->map(function ($number) { return new Some($number) ->map($this->transformationOne()) ->map($this->transformationTwo()) ->map($this->transformationThree() ->get(); }); }
  • 120. use PhpSlangCollectionParallelListCollection; … public function asyncChainedComputationExample(array $input) : ParallelListCollection { return (new ParallelListCollection($input)) ->map(function ($number) { return new Some($number) ->map($this->transformationOne()) ->map($this->transformationTwo()) ->map($this->transformationThree() ->get(); }); }
  • 121. What do I miss in PHP7 that Scala luckily has?
  • 122. :/ Immutability by default :) Objects cloning :) Options :) Either :/ Future :) Parallel collections ❏ Tail recurrency :( Generic types :( Arrow functions :)/:( Pattern matching / case classes
  • 124. def fibonacci(index : Int) : Int = index match { case 0 | 1 => index case _ => fibonacci(index - 1 ) + fibonacci(index - 2) } function fibonacci(int $index) : int { return in_array($index, [0, 1]) ? $index : fibonacci($index - 1) + fibonacci($index - 2); }
  • 125. def fibonacci(index : Int) : Int = index match { case 0 | 1 => index case _ => fibonacci(index - 1 ) + fibonacci(index - 2) } function fibonacci(int $index) : int { return in_array($index, [0, 1]) ? $index : fibonacci($index - 1) + fibonacci($index - 2); } echo fibonacci(123123123123); Fatal error: Maximum function nesting level of '...' reached, aborting!
  • 127. def fibonacci(index: Int): Int = { var a = 0 var b = 1 var i = 0 while (i < index) { val c = a + b a = b b = c i = i + 1 } return a } function fibonacci(int $index) : int { $a = 0; $b = 1; $i = 0; while ($i < $index) { $c = $a + $b; $a = $b; $b = $c; $i += 1; } return $a; }
  • 128. def recursiveFibonacci(n: Int, a:Int, b:Int): Int = n match { case 0 => a case _ => recursiveFibonacci( n-1, b, a+b ) } def fibonacci( n : Int) : Int = recursiveFibonacci( n, 0, 1) function recursiveFibonacci(int $n, int $a, int $b) { return ($n == 0) ? $a : recursiveFibonacci($n - 1, $b, $a + $b); } function fibonacci(int $n) : int { return recursiveFibonacci($n, 0, 1); }
  • 129. def fibonacci(index : Int) : Int = index match { case 0 | 1 => index case _ => fibonacci(index - 1 ) + fibonacci(index - 2) } function fibonacci(int $index) : int { return in_array($index, [0, 1]) ? $index : fibonacci($index - 1) + fibonacci($index - 2); }
  • 130. @tailrec def recursiveFibonacci(n: Int, a:Int, b:Int): Int = n match { case 0 => a case _ => recursiveFibonacci( n-1, b, a+b ) } def fibonacci( n : Int) : Int = recursiveFibonacci( n, 0, 1) function recursiveFibonacci(int $n, int $a, int $b) { return ($n == 0) ? $a : recursiveFibonacci($n - 1, $b, $a + $b); } function fibonacci(int $n) : int { return recursiveFibonacci($n, 0, 1); } :( :)
  • 134. function recursiveFibonacci(int $n, int $a, int $b) { return ($n == 0) ? $a : recursiveFibonacci($n - 1, $b, $a + $b); } function fibonacci($n) { return recursiveFibonacci($n, 0, 1); }
  • 135. function recursiveFibonacci(int $n, int $a, int $b) { return ($n == 0) ? new Done($a) : new Bounce(function () use ($n, $b, $a) { return recursiveFibonacci($n - 1, $b, $a + $b); }); } function fibonacci($n) { return (new Trampoline(function () use ($n) { return recursiveFibonacci($n, 0, 1); }))->run(); }
  • 137. What do I miss in PHP7 that Scala luckily has?
  • 138. :/ Immutability by default :) Objects cloning :) Options :) Either :/ Future :) Parallel collections :) Tail recurrency :( Generic types :( Arrow functions :)/:( Pattern matching / case classes
  • 140. Conclusions ● Don’t be afraid of monads ● Care about transparency (especially referential) ● Learn Haskell, Clojure, Scala, F#, JavaScript -> TypeScript