SlideShare a Scribd company logo
Witek Adamus
PHPCon 2016, Rawa Mazowiecka
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
❏ What can
functional
programming
bring to the
table?
❏ When language
can be
described as
functional?
Table of content
❏ DIY: cleaning ❏ Transparent parallelism
❏ Parallelism vs Concurrency
❏ Parallel collections
Table of content
Pros and cons of functional programming
Pros Cons
Efficiency Efficiency
Entry threshold Entry threshold
Mathematical
description of
reality
Mathematical
description of
reality
Pros and cons of functional programming
Pros Cons In result
Efficiency Efficiency Scalability
Entry threshold Entry threshold Let’s get the party
started
Mathematical
description of
reality
Mathematical
description of
reality
Shorter and more
descriptive code
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();
}
Fundamental concepts in functional programming
❏ Function is a first-class citizen
❏ No side effects
❏ Immutability
❏ Lambda Calculus
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)
No side effects? Immutability?
:(
Lambda Calculus
ƛ(x) = z
Lambda Calculus
ƛ(x) = z
❏ Higher-order functions
❏ Currying
Functional vs Object oriented programming
?
PHPCon 2016: PHP7 by Witek Adamus / XSolve
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
Few rules to
make your
code
functional
Do not use
❏ reassignments
❏ if
❏ null
❏ for
❏ foreach
Do not use
❏ reassignments
$bigHouse = new Building(5);
$smallerHouse = $bigHouse->setFloors(2);
echo $bigHouse->getFloors() . PHP_EOL;
echo $smallerHouse->getFloors() . PHP_EOLl;
$bigHouse = new Building(5);
$smallerHouse = $bigHouse->setFloors(2);
echo $bigHouse->getFloors() . PHP_EOL; //2
echo $smallerHouse->getFloors() . PHP_EOLl; //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;
}
}
class Building
{
protected $floors;
public function __construct(int $floors)
{
$this->floors = $floors;
}
public function getFloors() : int
{
return $this->floors;
}
private function setFloors(int $floors) : Building
{
$this->floors = $floors;
return $this;
}
public function withFloors(int $floors) : Building
{
return (clone($this))->setFloors($floors);
}
}
$bigHouse = new Building(5);
$smallerHouse = $bigHouse->withFloors(2);
echo $bigHouse->getFloors() . PHP_EOL; //5
echo $smallerHouse->getFloors() . PHP_EOLl; //2
trait Copy
{
public function copy($field, $value)
{
$clone = clone $this;
$clone->$field = $value;
return $clone;
}
}
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);
}
}
Few rules to
make your
code
functional
Do not use
:) reassignments
❏ if
❏ null
❏ for
❏ foreach
https://github.com/php-slang/php-slang
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?
Option
Fishy Monad Tutorial
http://maciejpirog.github.io/fishy/ (cc-by-sa)
Fishy Monad Tutorial
http://maciejpirog.github.io/fishy/ (cc-by-sa)
Fishy Monad Tutorial
http://maciejpirog.github.io/fishy/ (cc-by-sa)
Fishy Monad Tutorial
http://maciejpirog.github.io/fishy/ (cc-by-sa)
https://github.com/php-slang/php-slang
# composer require php-slang/php-slang
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
class UserRepository extends EntityRepository
{
public function findByEmail(string $email) : User
{
$user = $this->findOneByMail(['email' => $email]);
if (!$user instanceof User) {
throw new NotFoundException("oh my");
}
return $user;
}
}
public function findUserAction(string $email) :
Response
try {
$user = $this
->userRepository
->findByEmail($email);
return new Response($user);
} catch (NotFoundException $exception) {
return new Response([],
Response::HTTP_NOT_FOUND);
}
}
class UserRepository extends EntityRepository
{
public function findByEmail(string $email) : Option
{
return Option::of($this>findOneByMail(['email' => $email]));
}
}
public function findUserAction(string $email) : Response
return $this
->userRepository
->findByEmail($email));
->map(function (User $user) { return new Response($user); })
->getOrElse(new Response('', Response::HTTP_NOT_FOUND));
}
class UserRepository extends EntityRepository
{
public function findByEmail(string $email) : User
{
$user = $this->findOneByMail(['email' => $email]);
if (!$user instanceof User) {
throw new NotFoundException("oh my");
}
return $user;
}
}
public function findUserAction(string $email) : Response
try {
$user = $this
->userRepository
->findByEmail($email);
return new Response($user);
} catch (NotFoundException $exception) {
return new Response([], Response::HTTP_NOT_FOUND);
}
}
class UserRepository extends EntityRepository
{
public function findByEmail(string $email) : Option
{
return Option::of(
$this>findOneByMail(['email' => $email]));
}
}
public function findUserAction(string $email) : Response
return $this
->userRepository
->findByEmail($email));
->map(function (User $user) {
return new Response($user); })
->getOrElse(
new Response('', Response::HTTP_NOT_FOUND));
}
Option
How about nesting
public function displayNameForUser(string $email) : string
{
$this
->userRepository
->findByEmail($email)
->get()
->getFirstName();
}
public function displayNameForUser(string $email) : string
{
$this
->userRepository
->findByEmail($email)
->map(function (User $user) {
return $user->firstName;
})
->getOrElse('oh my');
}
public function displayNameForUser(string $email) : ???
{
$this
->userRepository
->findByEmail($email)
->map(function (User $user) {
return $user->getFirstName();
});
}
public function displayNameForUser(string $email) : ???
{
$this
->userRepository
->findByEmail($email)
->map(function (User $user) {
return $user->getFirstName();
});
}
?
public function displayNameForUser(string $email) : ???
{
$this
->userRepository
->findByEmail($email)
->map(function (User $user) {
return $user->getFirstName();
});
}
Option<Option<String>>
public function displayNameForUser(string $email) : Option
{
$this
->userRepository
->findByEmail($email)
->flatMap(function (User $user) {
return $user->getFirstName();
});
}
public function displayNameForUser(string $email) : string
{
$this
->userRepository
->findByEmail($email)
->flatMap(function (User $user) {
return $user->getFirstName();
})
->getOrElse($email);
}
public function displayNameForUser(string $email) : string
{
$this
->userRepository
->findByEmail($email)
->flatMap(function (User $user) {
return $user->getFirstName();
})
->getOrCall(function () use ($email) {
$this->getAlternative($email);
});
}
public function displayNameForUser(string $email) : string
{
$this
->userRepository
->findByEmail($email)
->flatMap(function (User $user) {
return $user->getFirstName();
})
->getOrCall($this->getAlternative($email));
}
public function displayNameForUser(string $email) : string
{
$this
->userRepository
->findByEmail($email)
->flatMap(function (User $user) {
return $user->getFirstName();
})
->getOrCall($this->getAlternative($email));
}
public function getAlternative(string $email) : Closure
{
return function () use (string $email) : string {
return $this->doSomethingElseWith($email);
};
}
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($this->getAlternative($email));
}
public function getAlternative(string $email) : Closure
{
return function () use (string $email) : string {
return $this->doSomethingElseWith($email);
};
}
public function displayNameForUser(string $email) : string
{
$this
->userRepository
->findByEmail($email)
->flatMap((User $user) => $user->getFirstName())
->getOrCall(() => $this->doSomethingElseWith($email))
}
:(
Generic types
public function maybeSomething(string $email) : Option
{
...
}
public function maybeSomething(string $email) : Option<string>
{
...
}
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
:(
/**
* @return Option<string>
*/
public function maybeSomething(string $email) : Option
{
...
}
https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md
:(
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()
public function findUserAction(string $email) : Response
try {
$user = $this
->userRepository
->findByEmail($email);
return new Response($user);
} catch (NotFoundException $exception) {
return new Response([], Response::HTTP_NOT_FOUND);
}
}
public function findUserAction(string $email) : Response
try {
$user = $this
->userRepository
->findByEmail($email);
return new Response($user);
} catch (NotFoundException $exception) {
return new Response([], Response::HTTP_NOT_FOUND);
} catch (ExternalServiceResponseException $exception) {
return new Response([], Response::HTTP_FAILED_DEPENDENCY);
} catch (IncorrectEmailException $exception) {
return new Response([], Response::HTTP_BAD_REQUEST);
} catch (UserNotAllowedException $exception) {
return new Response([], Response::HTTP_FORBIDDEN);
}
}
“Co jest piękniejszego niż rdest? No chyba tylko bylina rdestu, bo rzadziej występuje.”
Ohanhutep
interface ServiceError {}
class NotFound implements ServiceError {}
class ServiceNotWorking implements ServiceError {}
class Param2IsPoorlyFormatted implements ServiceError {}
public function getSomethingNontrivial(string $param1, string $param2, string $param3) : Either
{
...
}
Either<ServiceError, User>
public function exampleAction(
string $param1, string $param2, string $param3) : Response {
return $this
->userService
->getSomethingNontrivial($param1, $param2, $param3)
->left(function (ServiceError $someKindOfFailure) : Response {
new Case(ServiceNotWorking::class, new Response('', Response::HTTP_FAILED_DEPENDENCY)),
new Case(Param2IsPoorlyFormatted::class, new Response('', Response::HTTP_BAD_REQUEST)),
new Case(NotFound()::class, new Response([], Response::HTTP_NOT_FOUND));
})
->right(function (User $nonTrivialAllRight) : Response {
return new Response($nonTrivialAllRight, Response::HTTP_OK);
})
->get();
}
public function getSomethingNontrivial(
string $param1, string $param2, string $param3) : Either
{
return $this
->translateParam2($param2)
->map(function ($param2Translated) {
return new Right($this->getUserBy($param2Translated));
})
->getOrElse(new Left(new Param2IsPoorlyFormatted()));
}
public function getSomethingNontrivial(string $param1, string $param2, string $param3) : Either
{
return $this
->translateParam2($param2)
->map($this->handleWithTranslatedParam($param1, $param3))
->getOrElse(new Left(new Param2IsPoorlyFormatted()));
}
public function handleWithTranslatedParam(string $param1, string $param3) : Clojure
{
return function (Param2Translated $param2Translated) use ($param1, $param3) : Either {
return $this
->someOtherMagic($param2Translated, $param1, $param3)
->map(function (User $magicResult) use ($param1, $param3) : Either {
return new Right($magicResult);
})
->getOrElse(new Left(new ServiceNotWorking()));
};
}
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
public function exampleAction(string $param1, string $param2, string $param3) : Response
{
return $this
->userService
->getSomethingNontrivial($param1, $param2, $param3)
->left(function (ServiceError $someKindOfFailure) : Response {
return (Match::of($someKindOfFailure))->match(
new Case(ServiceNotWorking::class, new Response('', Response::HTTP_FAILED_DEPENDENCY)),
new Case(Param2IsPoorlyFormatted::class, new Response('', Response::HTTP_BAD_REQUEST)),
new Case(NotFound::class, new Response([], Response::HTTP_NOT_FOUND));
})
->right(function (User $nonTrivialAllRight) : Response {
return new Response($nonTrivialAllRight, Response::HTTP_OK);
})
->get();
}
def update(id: String): Action[JsValue] = Action.async(parse.json) { request =>
user.update(id, userConverterFactory.of(request.body).toInput)
.map {
case Right(user) => Ok(user)
case Left(UserService.UserNotFound) => NotFound
case Left(UserService.VersioningMissmatch) => NotAcceptable
case Left(UserService.NoModificationsAllowed) => Locked
case Left(UserService.InvalidPayload) => BadRequest
}
}
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
public function multiplyBy(
array $input, float $multiplication): array
{
$output = [];
foreach($input as $number)
{
$output[] = $number * $multiplication;
}
return $output;
}
use PhpSlangCollectionListCollection;
...
public function beautifulMultiplyBy(
array $input, float $multiplication) : ListCollection
{
return (new ListCollection($input))
->map(function ($number) use ($multiplication) {
return $number * $multiplication;
});
}
public function multiplyOddsBy(
array $input, float $multiplication): array
{
$output = [];
foreach ($input as $number) {
if ($number % 2 !== 0) {
$output[] = $number * $multiplication;
}
}
return $output;
}
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 . ' ';
});
}
PHPCon 2016: PHP7 by Witek Adamus / XSolve
(new ListCollection([1,2,3,4]))->tail(); //ArrayCollection([2,3,4])
Few rules to
make your
code
functional
Do not use
:) reassignments
:) if
:) null
:) for
:) foreach
Parallelism vs Concurrency
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
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>
Jak powinno to wyglądać?
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>
Jak powinno to wyglądać?
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>
Jak powinno to wyglądać?
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();
}
Jak powinno to wyglądać?
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();
}
Jak powinno to wyglądać?
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;
});
}
class ParallelListCollection extends ListCollection
{
public function map(Closure $func)
{
return Future::all(
(new ArrayCollection($this->elements))
->map(function ($element) use ($func) {
return new Future(function () use ($func, $element) {
return $func($element);
});
})
->toArray())
->await();
}
}
class ParallelListCollection extends ListCollection
{
public function map(Closure $func)
{
return Future::all(
(new ArrayCollection($this->elements))
->map(function ($element) use ($func) {
return new Future(function () use ($func, $element) {
return $func($element);
});
})
->toArray())
->await();
}
}
ArrayCollection<Future<mixed>>
Future<ArrayCollection<mixed>>
ArrayCollection<mixed>
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($this->transformationOne())
->map($this->transformationTwo())
->map($this->transformationThree();
}
use PhpSlangCollectionParallelListCollection;
...
public function asyncChainedComputationExample(array $input) : ParallelListCollection
{
return (new ParallelListCollection($input))
->map(function ($number) {
return Option::of($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 Option::of($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);
}
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
<?php
namespace PhpSlangUtilTrampoline;
...
class Trampoline
{
/**
* @var TrampolineResult
*/
var $expression;
public function __construct(Closure $expression)
{
$this->expression;
}
public function run()
{
$result = new Bounce(function () {
return ($this->expression)();
});
while ($result instanceof Bounce) {
$result = $result->run();
}
return $result->run()->get();
}
}
interface TrampolineResult
{
public function run() : TrampolineResult;
public function get();
}
class Bounce implements TrampolineResult {...}
class Done implements TrampolineResult {...}
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);
}
echo fibonacci(8);
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();
}
echo fibonacci(8);
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
PHPCon 2016: PHP7 by Witek Adamus / XSolve
Conclusions
● Don’t be afraid of monads
● Don’t set traps for your team
● Learn Haskell, Clojure, Scala, F#, JavaScript -> TypeScript
Witek Adamus
witold.adamus@xsolve.pl
xsolve.pl/nobodyexpects

More Related Content

What's hot

Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
Mark Baker
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
Konstantin Kudryashov
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
Kacper Gunia
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
Jace Ju
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
Konstantin Kudryashov
 
SfCon: Test Driven Development
SfCon: Test Driven DevelopmentSfCon: Test Driven Development
SfCon: Test Driven Development
Augusto Pascutti
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix it
Rafael Dohms
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
Hugo Hamon
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
Hugo Hamon
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHP
Guilherme Blanco
 
PHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsPHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object Calisthenics
Guilherme Blanco
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
Jorn Oomen
 
The road to continuous deployment (PHPCon Poland 2016)
The road to continuous deployment (PHPCon Poland 2016)The road to continuous deployment (PHPCon Poland 2016)
The road to continuous deployment (PHPCon Poland 2016)
Michiel Rook
 
Learning Perl 6 (NPW 2007)
Learning Perl 6 (NPW 2007)Learning Perl 6 (NPW 2007)
Learning Perl 6 (NPW 2007)
brian d foy
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
Seri Moth
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
jsmith92
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
Kirill Chebunin
 
Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)
Nikita Popov
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
Bill Chang
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
Leonardo Proietti
 

What's hot (20)

Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
SfCon: Test Driven Development
SfCon: Test Driven DevelopmentSfCon: Test Driven Development
SfCon: Test Driven Development
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix it
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHP
 
PHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsPHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object Calisthenics
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
The road to continuous deployment (PHPCon Poland 2016)
The road to continuous deployment (PHPCon Poland 2016)The road to continuous deployment (PHPCon Poland 2016)
The road to continuous deployment (PHPCon Poland 2016)
 
Learning Perl 6 (NPW 2007)
Learning Perl 6 (NPW 2007)Learning Perl 6 (NPW 2007)
Learning Perl 6 (NPW 2007)
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
 
Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 

Viewers also liked

How to be agile at Agile Hack?! - agilehack.pl
How to be agile at Agile Hack?! - agilehack.plHow to be agile at Agile Hack?! - agilehack.pl
How to be agile at Agile Hack?! - agilehack.pl
XSolve
 
Xsolve presentation - programming, bodyleasing, e-commerce
Xsolve presentation - programming, bodyleasing, e-commerceXsolve presentation - programming, bodyleasing, e-commerce
Xsolve presentation - programming, bodyleasing, e-commerce
XSolve
 
Piątek z XSolve - TravisCI & Continuous Delivery
Piątek z XSolve - TravisCI & Continuous DeliveryPiątek z XSolve - TravisCI & Continuous Delivery
Piątek z XSolve - TravisCI & Continuous Delivery
XSolve
 
Xlab #2: wzorce projektowe
Xlab #2: wzorce projektoweXlab #2: wzorce projektowe
Xlab #2: wzorce projektowe
XSolve
 
xlab #7 - ReactJS & NodeJS
xlab #7 - ReactJS & NodeJSxlab #7 - ReactJS & NodeJS
xlab #7 - ReactJS & NodeJS
XSolve
 
xlab #8 - Architektura mikroserwisów na platformie Spring Boot
xlab #8 - Architektura mikroserwisów na platformie Spring Bootxlab #8 - Architektura mikroserwisów na platformie Spring Boot
xlab #8 - Architektura mikroserwisów na platformie Spring Boot
XSolve
 
M&m's m.p. amarillo
M&m's m.p. amarilloM&m's m.p. amarillo
M&m's m.p. amarillo
Dani Vidal
 
Curso Web20 S1 Conversacion Distribuida
Curso Web20 S1 Conversacion DistribuidaCurso Web20 S1 Conversacion Distribuida
Curso Web20 S1 Conversacion Distribuida
Domingo Méndez
 
2ª circular foto orla 6º primaria 14 15
2ª circular foto orla 6º primaria 14 152ª circular foto orla 6º primaria 14 15
2ª circular foto orla 6º primaria 14 15
Cole Navalazarza
 
Hoja de vida. fernando mesa
Hoja de vida. fernando mesaHoja de vida. fernando mesa
Hoja de vida. fernando mesa
Ferdinand Messa Ochoa
 
Linux
LinuxLinux
Linux
Daniel Mf
 
Nuestra tierra 40 Geografía de la vida
Nuestra tierra 40 Geografía de la vidaNuestra tierra 40 Geografía de la vida
Nuestra tierra 40 Geografía de la vida
Ximena Sosa Motta
 
Futmondo
FutmondoFutmondo
Futmondo
betabeers
 
firmenkontor24
firmenkontor24firmenkontor24
firmenkontor24
infoprimus
 
Do the Chinese really lose face?
Do the Chinese really lose face?Do the Chinese really lose face?
Do the Chinese really lose face?
Daniela Fehring
 
Forum ICT Security 2015 - Identificare gli attacchi di nuova generazione medi...
Forum ICT Security 2015 - Identificare gli attacchi di nuova generazione medi...Forum ICT Security 2015 - Identificare gli attacchi di nuova generazione medi...
Forum ICT Security 2015 - Identificare gli attacchi di nuova generazione medi...
Par-Tec S.p.A.
 
Cuadrosdesebas
CuadrosdesebasCuadrosdesebas
Cuadrosdesebas
Sebas El Buen Gusto
 
Nmedia marketing escuela nautica - forca 6 - estudio de mercado gratis
Nmedia marketing   escuela nautica - forca 6 - estudio de mercado gratisNmedia marketing   escuela nautica - forca 6 - estudio de mercado gratis
Nmedia marketing escuela nautica - forca 6 - estudio de mercado gratis
NmediaMarketing
 
Codetwo Exchange Rules 2007 Users Manual - Exchange Disclaimer, Signature
Codetwo Exchange Rules 2007 Users Manual - Exchange Disclaimer, SignatureCodetwo Exchange Rules 2007 Users Manual - Exchange Disclaimer, Signature
Codetwo Exchange Rules 2007 Users Manual - Exchange Disclaimer, Signature
mi gen
 
Einladung Cleantech Konferenz
Einladung Cleantech KonferenzEinladung Cleantech Konferenz
Einladung Cleantech Konferenz
Spirofrog & Cleantech Europe - Jobs & Career
 

Viewers also liked (20)

How to be agile at Agile Hack?! - agilehack.pl
How to be agile at Agile Hack?! - agilehack.plHow to be agile at Agile Hack?! - agilehack.pl
How to be agile at Agile Hack?! - agilehack.pl
 
Xsolve presentation - programming, bodyleasing, e-commerce
Xsolve presentation - programming, bodyleasing, e-commerceXsolve presentation - programming, bodyleasing, e-commerce
Xsolve presentation - programming, bodyleasing, e-commerce
 
Piątek z XSolve - TravisCI & Continuous Delivery
Piątek z XSolve - TravisCI & Continuous DeliveryPiątek z XSolve - TravisCI & Continuous Delivery
Piątek z XSolve - TravisCI & Continuous Delivery
 
Xlab #2: wzorce projektowe
Xlab #2: wzorce projektoweXlab #2: wzorce projektowe
Xlab #2: wzorce projektowe
 
xlab #7 - ReactJS & NodeJS
xlab #7 - ReactJS & NodeJSxlab #7 - ReactJS & NodeJS
xlab #7 - ReactJS & NodeJS
 
xlab #8 - Architektura mikroserwisów na platformie Spring Boot
xlab #8 - Architektura mikroserwisów na platformie Spring Bootxlab #8 - Architektura mikroserwisów na platformie Spring Boot
xlab #8 - Architektura mikroserwisów na platformie Spring Boot
 
M&m's m.p. amarillo
M&m's m.p. amarilloM&m's m.p. amarillo
M&m's m.p. amarillo
 
Curso Web20 S1 Conversacion Distribuida
Curso Web20 S1 Conversacion DistribuidaCurso Web20 S1 Conversacion Distribuida
Curso Web20 S1 Conversacion Distribuida
 
2ª circular foto orla 6º primaria 14 15
2ª circular foto orla 6º primaria 14 152ª circular foto orla 6º primaria 14 15
2ª circular foto orla 6º primaria 14 15
 
Hoja de vida. fernando mesa
Hoja de vida. fernando mesaHoja de vida. fernando mesa
Hoja de vida. fernando mesa
 
Linux
LinuxLinux
Linux
 
Nuestra tierra 40 Geografía de la vida
Nuestra tierra 40 Geografía de la vidaNuestra tierra 40 Geografía de la vida
Nuestra tierra 40 Geografía de la vida
 
Futmondo
FutmondoFutmondo
Futmondo
 
firmenkontor24
firmenkontor24firmenkontor24
firmenkontor24
 
Do the Chinese really lose face?
Do the Chinese really lose face?Do the Chinese really lose face?
Do the Chinese really lose face?
 
Forum ICT Security 2015 - Identificare gli attacchi di nuova generazione medi...
Forum ICT Security 2015 - Identificare gli attacchi di nuova generazione medi...Forum ICT Security 2015 - Identificare gli attacchi di nuova generazione medi...
Forum ICT Security 2015 - Identificare gli attacchi di nuova generazione medi...
 
Cuadrosdesebas
CuadrosdesebasCuadrosdesebas
Cuadrosdesebas
 
Nmedia marketing escuela nautica - forca 6 - estudio de mercado gratis
Nmedia marketing   escuela nautica - forca 6 - estudio de mercado gratisNmedia marketing   escuela nautica - forca 6 - estudio de mercado gratis
Nmedia marketing escuela nautica - forca 6 - estudio de mercado gratis
 
Codetwo Exchange Rules 2007 Users Manual - Exchange Disclaimer, Signature
Codetwo Exchange Rules 2007 Users Manual - Exchange Disclaimer, SignatureCodetwo Exchange Rules 2007 Users Manual - Exchange Disclaimer, Signature
Codetwo Exchange Rules 2007 Users Manual - Exchange Disclaimer, Signature
 
Einladung Cleantech Konferenz
Einladung Cleantech KonferenzEinladung Cleantech Konferenz
Einladung Cleantech Konferenz
 

Similar to PHPCon 2016: PHP7 by Witek Adamus / XSolve

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?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?
Lucas Witold Adamus
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
Stoyan Stefanov
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
Jeff Carouth
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
Sam Hennessy
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
Divante
 
Functional php
Functional phpFunctional php
Functional php
Jean Carlo Machado
 
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSLPHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
iMasters
 
Object Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPObject Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOP
Wildan Maulana
 
Oops in php
Oops in phpOops in php
Hack tutorial
Hack tutorialHack tutorial
Hack tutorial
Wakana Yoshizawa
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
Lars Jankowfsky
 
Functional programming with php7
Functional programming with php7Functional programming with php7
Functional programming with php7
Sérgio Rafael Siqueira
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
Abbas Ali
 
Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5
Stephan Schmidt
 
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
James Titcumb
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
elliando dias
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
Marcello Duarte
 
Durian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middlewareDurian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middleware
Kuan Yen Heng
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
Kang-min Liu
 
Generating Power with Yield
Generating Power with YieldGenerating Power with Yield
Generating Power with Yield
Jason Myers
 

Similar to PHPCon 2016: PHP7 by Witek Adamus / XSolve (20)

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?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?
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
Functional php
Functional phpFunctional php
Functional php
 
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSLPHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
 
Object Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPObject Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOP
 
Oops in php
Oops in phpOops in php
Oops in php
 
Hack tutorial
Hack tutorialHack tutorial
Hack tutorial
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Functional programming with php7
Functional programming with php7Functional programming with php7
Functional programming with php7
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5Go OO! - Real-life Design Patterns in PHP 5
Go OO! - Real-life Design Patterns in PHP 5
 
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Durian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middlewareDurian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middleware
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
 
Generating Power with Yield
Generating Power with YieldGenerating Power with Yield
Generating Power with Yield
 

More from XSolve

Jak migrować kod legacy do Symfony? Tips & tricks
Jak migrować kod legacy do Symfony? Tips & tricksJak migrować kod legacy do Symfony? Tips & tricks
Jak migrować kod legacy do Symfony? Tips & tricks
XSolve
 
How to Create an Agile Office
How to Create an Agile OfficeHow to Create an Agile Office
How to Create an Agile Office
XSolve
 
Xlab #10: Integracja zewnętrznych API z wykorzystaniem platformy Spring
Xlab #10: Integracja zewnętrznych API z wykorzystaniem platformy SpringXlab #10: Integracja zewnętrznych API z wykorzystaniem platformy Spring
Xlab #10: Integracja zewnętrznych API z wykorzystaniem platformy Spring
XSolve
 
How to build a Tesla car for the price of a Chevrolet
How to build a Tesla car for the price of a ChevroletHow to build a Tesla car for the price of a Chevrolet
How to build a Tesla car for the price of a Chevrolet
XSolve
 
Piątek z XSolve - Bezpieczne nagłówki HTTP
Piątek z XSolve - Bezpieczne nagłówki HTTPPiątek z XSolve - Bezpieczne nagłówki HTTP
Piątek z XSolve - Bezpieczne nagłówki HTTP
XSolve
 
Grafowa baza danych i integracja z symfony
Grafowa baza danych  i integracja z symfonyGrafowa baza danych  i integracja z symfony
Grafowa baza danych i integracja z symfony
XSolve
 
How to outsource Scrum projects - a guide
How to outsource Scrum projects - a guideHow to outsource Scrum projects - a guide
How to outsource Scrum projects - a guide
XSolve
 
Prezentacja firmy XSolve - programowanie, e-commerce, bodyleasing
Prezentacja firmy XSolve - programowanie, e-commerce, bodyleasingPrezentacja firmy XSolve - programowanie, e-commerce, bodyleasing
Prezentacja firmy XSolve - programowanie, e-commerce, bodyleasing
XSolve
 
Dlaczego git to nie svn oraz dlaczego to dobrze ?
Dlaczego git to nie svn oraz dlaczego to dobrze ?Dlaczego git to nie svn oraz dlaczego to dobrze ?
Dlaczego git to nie svn oraz dlaczego to dobrze ?
XSolve
 
Programowanie zorientowane aspektowo
Programowanie zorientowane aspektowoProgramowanie zorientowane aspektowo
Programowanie zorientowane aspektowo
XSolve
 
Agile estimating and planning
Agile estimating and planningAgile estimating and planning
Agile estimating and planning
XSolve
 
Tailoring of PRINCE2
Tailoring of PRINCE2Tailoring of PRINCE2
Tailoring of PRINCE2
XSolve
 
Mongo db baza danych zorientowana dokumentowo
Mongo db  baza danych zorientowana dokumentowo Mongo db  baza danych zorientowana dokumentowo
Mongo db baza danych zorientowana dokumentowo
XSolve
 
Debugowanie skryptow php za pomoca xdebug
Debugowanie skryptow php za pomoca xdebugDebugowanie skryptow php za pomoca xdebug
Debugowanie skryptow php za pomoca xdebug
XSolve
 
Zarządzanie projektami w XSolve
Zarządzanie projektami w XSolveZarządzanie projektami w XSolve
Zarządzanie projektami w XSolve
XSolve
 

More from XSolve (15)

Jak migrować kod legacy do Symfony? Tips & tricks
Jak migrować kod legacy do Symfony? Tips & tricksJak migrować kod legacy do Symfony? Tips & tricks
Jak migrować kod legacy do Symfony? Tips & tricks
 
How to Create an Agile Office
How to Create an Agile OfficeHow to Create an Agile Office
How to Create an Agile Office
 
Xlab #10: Integracja zewnętrznych API z wykorzystaniem platformy Spring
Xlab #10: Integracja zewnętrznych API z wykorzystaniem platformy SpringXlab #10: Integracja zewnętrznych API z wykorzystaniem platformy Spring
Xlab #10: Integracja zewnętrznych API z wykorzystaniem platformy Spring
 
How to build a Tesla car for the price of a Chevrolet
How to build a Tesla car for the price of a ChevroletHow to build a Tesla car for the price of a Chevrolet
How to build a Tesla car for the price of a Chevrolet
 
Piątek z XSolve - Bezpieczne nagłówki HTTP
Piątek z XSolve - Bezpieczne nagłówki HTTPPiątek z XSolve - Bezpieczne nagłówki HTTP
Piątek z XSolve - Bezpieczne nagłówki HTTP
 
Grafowa baza danych i integracja z symfony
Grafowa baza danych  i integracja z symfonyGrafowa baza danych  i integracja z symfony
Grafowa baza danych i integracja z symfony
 
How to outsource Scrum projects - a guide
How to outsource Scrum projects - a guideHow to outsource Scrum projects - a guide
How to outsource Scrum projects - a guide
 
Prezentacja firmy XSolve - programowanie, e-commerce, bodyleasing
Prezentacja firmy XSolve - programowanie, e-commerce, bodyleasingPrezentacja firmy XSolve - programowanie, e-commerce, bodyleasing
Prezentacja firmy XSolve - programowanie, e-commerce, bodyleasing
 
Dlaczego git to nie svn oraz dlaczego to dobrze ?
Dlaczego git to nie svn oraz dlaczego to dobrze ?Dlaczego git to nie svn oraz dlaczego to dobrze ?
Dlaczego git to nie svn oraz dlaczego to dobrze ?
 
Programowanie zorientowane aspektowo
Programowanie zorientowane aspektowoProgramowanie zorientowane aspektowo
Programowanie zorientowane aspektowo
 
Agile estimating and planning
Agile estimating and planningAgile estimating and planning
Agile estimating and planning
 
Tailoring of PRINCE2
Tailoring of PRINCE2Tailoring of PRINCE2
Tailoring of PRINCE2
 
Mongo db baza danych zorientowana dokumentowo
Mongo db  baza danych zorientowana dokumentowo Mongo db  baza danych zorientowana dokumentowo
Mongo db baza danych zorientowana dokumentowo
 
Debugowanie skryptow php za pomoca xdebug
Debugowanie skryptow php za pomoca xdebugDebugowanie skryptow php za pomoca xdebug
Debugowanie skryptow php za pomoca xdebug
 
Zarządzanie projektami w XSolve
Zarządzanie projektami w XSolveZarządzanie projektami w XSolve
Zarządzanie projektami w XSolve
 

Recently uploaded

UX Webinar Series: Essentials for Adopting Passkeys as the Foundation of your...
UX Webinar Series: Essentials for Adopting Passkeys as the Foundation of your...UX Webinar Series: Essentials for Adopting Passkeys as the Foundation of your...
UX Webinar Series: Essentials for Adopting Passkeys as the Foundation of your...
FIDO Alliance
 
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and DisadvantagesBLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
SAI KAILASH R
 
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
alexjohnson7307
 
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Zilliz
 
Opencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of MünsterOpencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of Münster
Matthias Neugebauer
 
Keynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive SecurityKeynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive Security
Priyanka Aash
 
Uncharted Together- Navigating AI's New Frontiers in Libraries
Uncharted Together- Navigating AI's New Frontiers in LibrariesUncharted Together- Navigating AI's New Frontiers in Libraries
Uncharted Together- Navigating AI's New Frontiers in Libraries
Brian Pichman
 
Perth MuleSoft Meetup July 2024
Perth MuleSoft Meetup July 2024Perth MuleSoft Meetup July 2024
Perth MuleSoft Meetup July 2024
Michael Price
 
It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...
Zilliz
 
Tailored CRM Software Development for Enhanced Customer Insights
Tailored CRM Software Development for Enhanced Customer InsightsTailored CRM Software Development for Enhanced Customer Insights
Tailored CRM Software Development for Enhanced Customer Insights
SynapseIndia
 
Camunda Chapter NY Meetup July 2024.pptx
Camunda Chapter NY Meetup July 2024.pptxCamunda Chapter NY Meetup July 2024.pptx
Camunda Chapter NY Meetup July 2024.pptx
ZachWylie3
 
Redefining Cybersecurity with AI Capabilities
Redefining Cybersecurity with AI CapabilitiesRedefining Cybersecurity with AI Capabilities
Redefining Cybersecurity with AI Capabilities
Priyanka Aash
 
Accelerating Migrations = Recommendations
Accelerating Migrations = RecommendationsAccelerating Migrations = Recommendations
Accelerating Migrations = Recommendations
isBullShit
 
Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024
Nicolás Lopéz
 
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
OnBoard
 
NVIDIA at Breakthrough Discuss for Space Exploration
NVIDIA at Breakthrough Discuss for Space ExplorationNVIDIA at Breakthrough Discuss for Space Exploration
NVIDIA at Breakthrough Discuss for Space Exploration
Alison B. Lowndes
 
Improving Learning Content Efficiency with Reusable Learning Content
Improving Learning Content Efficiency with Reusable Learning ContentImproving Learning Content Efficiency with Reusable Learning Content
Improving Learning Content Efficiency with Reusable Learning Content
Enterprise Knowledge
 
Zaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdfZaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdf
AmandaCheung15
 
Integrating Kafka with MuleSoft 4 and usecase
Integrating Kafka with MuleSoft 4 and usecaseIntegrating Kafka with MuleSoft 4 and usecase
Integrating Kafka with MuleSoft 4 and usecase
shyamraj55
 
Types of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technologyTypes of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technology
ldtexsolbl
 

Recently uploaded (20)

UX Webinar Series: Essentials for Adopting Passkeys as the Foundation of your...
UX Webinar Series: Essentials for Adopting Passkeys as the Foundation of your...UX Webinar Series: Essentials for Adopting Passkeys as the Foundation of your...
UX Webinar Series: Essentials for Adopting Passkeys as the Foundation of your...
 
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and DisadvantagesBLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
 
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
 
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
 
Opencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of MünsterOpencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of Münster
 
Keynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive SecurityKeynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive Security
 
Uncharted Together- Navigating AI's New Frontiers in Libraries
Uncharted Together- Navigating AI's New Frontiers in LibrariesUncharted Together- Navigating AI's New Frontiers in Libraries
Uncharted Together- Navigating AI's New Frontiers in Libraries
 
Perth MuleSoft Meetup July 2024
Perth MuleSoft Meetup July 2024Perth MuleSoft Meetup July 2024
Perth MuleSoft Meetup July 2024
 
It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...
 
Tailored CRM Software Development for Enhanced Customer Insights
Tailored CRM Software Development for Enhanced Customer InsightsTailored CRM Software Development for Enhanced Customer Insights
Tailored CRM Software Development for Enhanced Customer Insights
 
Camunda Chapter NY Meetup July 2024.pptx
Camunda Chapter NY Meetup July 2024.pptxCamunda Chapter NY Meetup July 2024.pptx
Camunda Chapter NY Meetup July 2024.pptx
 
Redefining Cybersecurity with AI Capabilities
Redefining Cybersecurity with AI CapabilitiesRedefining Cybersecurity with AI Capabilities
Redefining Cybersecurity with AI Capabilities
 
Accelerating Migrations = Recommendations
Accelerating Migrations = RecommendationsAccelerating Migrations = Recommendations
Accelerating Migrations = Recommendations
 
Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024Vertex AI Agent Builder - GDG Alicante - Julio 2024
Vertex AI Agent Builder - GDG Alicante - Julio 2024
 
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
 
NVIDIA at Breakthrough Discuss for Space Exploration
NVIDIA at Breakthrough Discuss for Space ExplorationNVIDIA at Breakthrough Discuss for Space Exploration
NVIDIA at Breakthrough Discuss for Space Exploration
 
Improving Learning Content Efficiency with Reusable Learning Content
Improving Learning Content Efficiency with Reusable Learning ContentImproving Learning Content Efficiency with Reusable Learning Content
Improving Learning Content Efficiency with Reusable Learning Content
 
Zaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdfZaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdf
 
Integrating Kafka with MuleSoft 4 and usecase
Integrating Kafka with MuleSoft 4 and usecaseIntegrating Kafka with MuleSoft 4 and usecase
Integrating Kafka with MuleSoft 4 and usecase
 
Types of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technologyTypes of Weaving loom machine & it's technology
Types of Weaving loom machine & it's technology
 

PHPCon 2016: PHP7 by Witek Adamus / XSolve

  • 1. Witek Adamus PHPCon 2016, Rawa Mazowiecka
  • 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. ❏ What can functional programming bring to the table? ❏ When language can be described as functional? Table of content
  • 6. ❏ DIY: cleaning ❏ Transparent parallelism ❏ Parallelism vs Concurrency ❏ Parallel collections Table of content
  • 7. Pros and cons of functional programming Pros Cons Efficiency Efficiency Entry threshold Entry threshold Mathematical description of reality Mathematical description of reality
  • 8. Pros and cons of functional programming Pros Cons In result Efficiency Efficiency Scalability Entry threshold Entry threshold Let’s get the party started Mathematical description of reality Mathematical description of reality Shorter and more descriptive code
  • 9. 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; }
  • 10. 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(); }
  • 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; } 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(); }
  • 12. Fundamental concepts in functional programming ❏ Function is a first-class citizen ❏ No side effects ❏ Immutability ❏ Lambda Calculus
  • 13. 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)
  • 14. No side effects? Immutability? :(
  • 16. Lambda Calculus ƛ(x) = z ❏ Higher-order functions ❏ Currying
  • 17. Functional vs Object oriented programming ?
  • 19. PHP7 is functional …but is dirty and salty as well
  • 20. What do I miss in PHP7 that Scala luckily has?
  • 21. ❏ Immutability by default ❏ Objects cloning ❏ Options ❏ Either ❏ Future ❏ Parallel collections ❏ Tail recurrency ❏ Generic types ❏ Arrow functions ❏ Pattern matching / case classes
  • 22. Few rules to make your code functional
  • 23. Do not use ❏ reassignments ❏ if ❏ null ❏ for ❏ foreach
  • 24. Do not use ❏ reassignments
  • 25. $bigHouse = new Building(5); $smallerHouse = $bigHouse->setFloors(2); echo $bigHouse->getFloors() . PHP_EOL; echo $smallerHouse->getFloors() . PHP_EOLl;
  • 26. $bigHouse = new Building(5); $smallerHouse = $bigHouse->setFloors(2); echo $bigHouse->getFloors() . PHP_EOL; //2 echo $smallerHouse->getFloors() . PHP_EOLl; //2
  • 27. 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; } }
  • 28. class Building { protected $floors; public function __construct(int $floors) { $this->floors = $floors; } public function getFloors() : int { return $this->floors; } private function setFloors(int $floors) : Building { $this->floors = $floors; return $this; } public function withFloors(int $floors) : Building { return (clone($this))->setFloors($floors); } }
  • 29. $bigHouse = new Building(5); $smallerHouse = $bigHouse->withFloors(2); echo $bigHouse->getFloors() . PHP_EOL; //5 echo $smallerHouse->getFloors() . PHP_EOLl; //2
  • 30. trait Copy { public function copy($field, $value) { $clone = clone $this; $clone->$field = $value; return $clone; } }
  • 31. 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); } }
  • 32. Few rules to make your code functional
  • 33. Do not use :) reassignments ❏ if ❏ null ❏ for ❏ foreach
  • 35. Do not use :) reassignments ❏ if ❏ null ❏ for ❏ foreach ?
  • 36. Do not use :) reassignments ❏ if ❏ null ❏ for ❏ foreach Option
  • 37. Option Monad which may contain something or nothing
  • 38. What is a monad? Option
  • 48. class UserRepository extends EntityRepository { public function findByEmail(string $email) : User { $user = $this->findOneByMail(['email' => $email]); if (!$user instanceof User) { throw new NotFoundException("oh my"); } return $user; } } public function findUserAction(string $email) : Response try { $user = $this ->userRepository ->findByEmail($email); return new Response($user); } catch (NotFoundException $exception) { return new Response([], Response::HTTP_NOT_FOUND); } }
  • 49. class UserRepository extends EntityRepository { public function findByEmail(string $email) : Option { return Option::of($this>findOneByMail(['email' => $email])); } } public function findUserAction(string $email) : Response return $this ->userRepository ->findByEmail($email)); ->map(function (User $user) { return new Response($user); }) ->getOrElse(new Response('', Response::HTTP_NOT_FOUND)); }
  • 50. class UserRepository extends EntityRepository { public function findByEmail(string $email) : User { $user = $this->findOneByMail(['email' => $email]); if (!$user instanceof User) { throw new NotFoundException("oh my"); } return $user; } } public function findUserAction(string $email) : Response try { $user = $this ->userRepository ->findByEmail($email); return new Response($user); } catch (NotFoundException $exception) { return new Response([], Response::HTTP_NOT_FOUND); } } class UserRepository extends EntityRepository { public function findByEmail(string $email) : Option { return Option::of( $this>findOneByMail(['email' => $email])); } } public function findUserAction(string $email) : Response return $this ->userRepository ->findByEmail($email)); ->map(function (User $user) { return new Response($user); }) ->getOrElse( new Response('', Response::HTTP_NOT_FOUND)); }
  • 52. public function displayNameForUser(string $email) : string { $this ->userRepository ->findByEmail($email) ->get() ->getFirstName(); }
  • 53. public function displayNameForUser(string $email) : string { $this ->userRepository ->findByEmail($email) ->map(function (User $user) { return $user->firstName; }) ->getOrElse('oh my'); }
  • 54. public function displayNameForUser(string $email) : ??? { $this ->userRepository ->findByEmail($email) ->map(function (User $user) { return $user->getFirstName(); }); }
  • 55. public function displayNameForUser(string $email) : ??? { $this ->userRepository ->findByEmail($email) ->map(function (User $user) { return $user->getFirstName(); }); } ?
  • 56. public function displayNameForUser(string $email) : ??? { $this ->userRepository ->findByEmail($email) ->map(function (User $user) { return $user->getFirstName(); }); } Option<Option<String>>
  • 57. public function displayNameForUser(string $email) : Option { $this ->userRepository ->findByEmail($email) ->flatMap(function (User $user) { return $user->getFirstName(); }); }
  • 58. public function displayNameForUser(string $email) : string { $this ->userRepository ->findByEmail($email) ->flatMap(function (User $user) { return $user->getFirstName(); }) ->getOrElse($email); }
  • 59. public function displayNameForUser(string $email) : string { $this ->userRepository ->findByEmail($email) ->flatMap(function (User $user) { return $user->getFirstName(); }) ->getOrCall(function () use ($email) { $this->getAlternative($email); }); }
  • 60. public function displayNameForUser(string $email) : string { $this ->userRepository ->findByEmail($email) ->flatMap(function (User $user) { return $user->getFirstName(); }) ->getOrCall($this->getAlternative($email)); }
  • 61. public function displayNameForUser(string $email) : string { $this ->userRepository ->findByEmail($email) ->flatMap(function (User $user) { return $user->getFirstName(); }) ->getOrCall($this->getAlternative($email)); } public function getAlternative(string $email) : Closure { return function () use (string $email) : string { return $this->doSomethingElseWith($email); }; }
  • 62. Few rules to make your code functional
  • 63. Do not use :) reassignments :) if :) null ❏ for ❏ foreach
  • 65. public function displayNameForUser(string $email) : string { return $this ->userRepository ->findByEmail($email) ->flatMap(function (User $user) { return $user->getFirstName(); }) ->getOrCall($this->getAlternative($email)); } public function getAlternative(string $email) : Closure { return function () use (string $email) : string { return $this->doSomethingElseWith($email); }; }
  • 66. public function displayNameForUser(string $email) : string { $this ->userRepository ->findByEmail($email) ->flatMap((User $user) => $user->getFirstName()) ->getOrCall(() => $this->doSomethingElseWith($email)) } :(
  • 68. public function maybeSomething(string $email) : Option { ... }
  • 69. public function maybeSomething(string $email) : Option<string> { ... }
  • 70. 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 :(
  • 71. /** * @return Option<string> */ public function maybeSomething(string $email) : Option { ... } https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md :(
  • 72. What do I miss in PHP7 that Scala luckily has?
  • 73. :) Immutability by default :) Objects cloning :) Options ❏ Either ❏ Future ❏ Parallel collections ❏ Tail recurrency :( Generic types :( Arrow functions ❏ Pattern matching / case classes
  • 76. Either Either RightLeft left(Closure $expr): Either right(Closure $expr): Either get() left(Closure $expr): Either right(Closure $expr): Either get()
  • 77. public function findUserAction(string $email) : Response try { $user = $this ->userRepository ->findByEmail($email); return new Response($user); } catch (NotFoundException $exception) { return new Response([], Response::HTTP_NOT_FOUND); } }
  • 78. public function findUserAction(string $email) : Response try { $user = $this ->userRepository ->findByEmail($email); return new Response($user); } catch (NotFoundException $exception) { return new Response([], Response::HTTP_NOT_FOUND); } catch (ExternalServiceResponseException $exception) { return new Response([], Response::HTTP_FAILED_DEPENDENCY); } catch (IncorrectEmailException $exception) { return new Response([], Response::HTTP_BAD_REQUEST); } catch (UserNotAllowedException $exception) { return new Response([], Response::HTTP_FORBIDDEN); } } “Co jest piękniejszego niż rdest? No chyba tylko bylina rdestu, bo rzadziej występuje.” Ohanhutep
  • 79. interface ServiceError {} class NotFound implements ServiceError {} class ServiceNotWorking implements ServiceError {} class Param2IsPoorlyFormatted implements ServiceError {} public function getSomethingNontrivial(string $param1, string $param2, string $param3) : Either { ... } Either<ServiceError, User>
  • 80. public function exampleAction( string $param1, string $param2, string $param3) : Response { return $this ->userService ->getSomethingNontrivial($param1, $param2, $param3) ->left(function (ServiceError $someKindOfFailure) : Response { new Case(ServiceNotWorking::class, new Response('', Response::HTTP_FAILED_DEPENDENCY)), new Case(Param2IsPoorlyFormatted::class, new Response('', Response::HTTP_BAD_REQUEST)), new Case(NotFound()::class, new Response([], Response::HTTP_NOT_FOUND)); }) ->right(function (User $nonTrivialAllRight) : Response { return new Response($nonTrivialAllRight, Response::HTTP_OK); }) ->get(); }
  • 81. public function getSomethingNontrivial( string $param1, string $param2, string $param3) : Either { return $this ->translateParam2($param2) ->map(function ($param2Translated) { return new Right($this->getUserBy($param2Translated)); }) ->getOrElse(new Left(new Param2IsPoorlyFormatted())); }
  • 82. public function getSomethingNontrivial(string $param1, string $param2, string $param3) : Either { return $this ->translateParam2($param2) ->map($this->handleWithTranslatedParam($param1, $param3)) ->getOrElse(new Left(new Param2IsPoorlyFormatted())); } public function handleWithTranslatedParam(string $param1, string $param3) : Clojure { return function (Param2Translated $param2Translated) use ($param1, $param3) : Either { return $this ->someOtherMagic($param2Translated, $param1, $param3) ->map(function (User $magicResult) use ($param1, $param3) : Either { return new Right($magicResult); }) ->getOrElse(new Left(new ServiceNotWorking())); }; }
  • 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
  • 86. public function exampleAction(string $param1, string $param2, string $param3) : Response { return $this ->userService ->getSomethingNontrivial($param1, $param2, $param3) ->left(function (ServiceError $someKindOfFailure) : Response { return (Match::of($someKindOfFailure))->match( new Case(ServiceNotWorking::class, new Response('', Response::HTTP_FAILED_DEPENDENCY)), new Case(Param2IsPoorlyFormatted::class, new Response('', Response::HTTP_BAD_REQUEST)), new Case(NotFound::class, new Response([], Response::HTTP_NOT_FOUND)); }) ->right(function (User $nonTrivialAllRight) : Response { return new Response($nonTrivialAllRight, Response::HTTP_OK); }) ->get(); }
  • 87. def update(id: String): Action[JsValue] = Action.async(parse.json) { request => user.update(id, userConverterFactory.of(request.body).toInput) .map { case Right(user) => Ok(user) case Left(UserService.UserNotFound) => NotFound case Left(UserService.VersioningMissmatch) => NotAcceptable case Left(UserService.NoModificationsAllowed) => Locked case Left(UserService.InvalidPayload) => BadRequest } }
  • 88. What do I miss in PHP7 that Scala luckily has?
  • 89. :) Immutability by default :) Objects cloning :) Options :) Either ❏ Future ❏ Parallel collections ❏ Tail recurrency :( Generic types :( Arrow functions :)/:( Pattern matching / case classes
  • 91. public function multiplyBy( array $input, float $multiplication): array { $output = []; foreach($input as $number) { $output[] = $number * $multiplication; } return $output; }
  • 92. use PhpSlangCollectionListCollection; ... public function beautifulMultiplyBy( array $input, float $multiplication) : ListCollection { return (new ListCollection($input)) ->map(function ($number) use ($multiplication) { return $number * $multiplication; }); }
  • 93. public function multiplyOddsBy( array $input, float $multiplication): array { $output = []; foreach ($input as $number) { if ($number % 2 !== 0) { $output[] = $number * $multiplication; } } return $output; }
  • 94. 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; }); }
  • 95. public function accumulatedText(array $words) : string { $text = ''; foreach ($words as $word) { $text .= $word . ' '; } return $text; }
  • 96. public function accumulatedText(array $words) : string { return (new ListCollection($words)) ->fold('', function (string $acumulator, string $word) { return $acumulator . $word . ' '; }); }
  • 99. Few rules to make your code functional
  • 100. Do not use :) reassignments :) if :) null :) for :) foreach
  • 104. Future
  • 105. 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(); }
  • 106. 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> Jak powinno to wyglądać?
  • 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(); } Future<NonBlockingGetResult> Jak powinno to wyglądać? Future<Response>
  • 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> Jak powinno to wyglądać? Future<Response> Response
  • 109. 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(); } Jak powinno to wyglądać?
  • 110. 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(); } Jak powinno to wyglądać?
  • 111. Future & Parallel collections
  • 112. use PhpSlangCollectionListCollection; ... public function beautifulMultiplyBy( array $input, float $multiplication) : ListCollection { return (new ListCollection($input)) ->map(function ($number) use ($multiplication) { return $number * $multiplication; }); }
  • 113. use PhpSlangCollectionParallelListCollection; ... public function beautifulMultiplyBy( array $input, float $multiplication) : ParallelListCollection { return (new ParallelListCollection($input)) ->map(function ($number) use ($multiplication) { return $number * $multiplication; }); }
  • 114. class ParallelListCollection extends ListCollection { public function map(Closure $func) { return Future::all( (new ArrayCollection($this->elements)) ->map(function ($element) use ($func) { return new Future(function () use ($func, $element) { return $func($element); }); }) ->toArray()) ->await(); } }
  • 115. class ParallelListCollection extends ListCollection { public function map(Closure $func) { return Future::all( (new ArrayCollection($this->elements)) ->map(function ($element) use ($func) { return new Future(function () use ($func, $element) { return $func($element); }); }) ->toArray()) ->await(); } } ArrayCollection<Future<mixed>> Future<ArrayCollection<mixed>> ArrayCollection<mixed>
  • 116. use PhpSlangCollectionParallelListCollection; ... public function asyncChainedComputationExample(array $input) : ParallelListCollection { return (new ParallelListCollection($input)) ->map($this->transformationOne()) ->map($this->transformationTwo()) ->map($this->transformationThree(); }
  • 117. use PhpSlangCollectionParallelListCollection; ... public function asyncChainedComputationExample(array $input) : ParallelListCollection { return (new ParallelListCollection($input)) ->map($this->transformationOne()) ->map($this->transformationTwo()) ->map($this->transformationThree(); }
  • 118. use PhpSlangCollectionParallelListCollection; ... public function asyncChainedComputationExample(array $input) : ParallelListCollection { return (new ParallelListCollection($input)) ->map(function ($number) { return Option::of($number) ->map($this->transformationOne()) ->map($this->transformationTwo()) ->map($this->transformationThree() ->get(); }); }
  • 119. use PhpSlangCollectionParallelListCollection; … public function asyncChainedComputationExample(array $input) : ParallelListCollection { return (new ParallelListCollection($input)) ->map(function ($number) { return Option::of($number) ->map($this->transformationOne()) ->map($this->transformationTwo()) ->map($this->transformationThree() ->get(); }); }
  • 120. What do I miss in PHP7 that Scala luckily has?
  • 121. :) Immutability by default :) Objects cloning :) Options :) Either :)/:( Future :) Parallel collections ❏ Tail recurrency :( Generic types :( Arrow functions :)/:( Pattern matching / case classes
  • 123. 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); }
  • 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); } echo fibonacci(123123123123); Fatal error: Maximum function nesting level of '...' reached, aborting!
  • 126. 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; }
  • 127. 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); }
  • 128. 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); }
  • 129. 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); } :(
  • 133. <?php namespace PhpSlangUtilTrampoline; ... class Trampoline { /** * @var TrampolineResult */ var $expression; public function __construct(Closure $expression) { $this->expression; } public function run() { $result = new Bounce(function () { return ($this->expression)(); }); while ($result instanceof Bounce) { $result = $result->run(); } return $result->run()->get(); } } interface TrampolineResult { public function run() : TrampolineResult; public function get(); } class Bounce implements TrampolineResult {...} class Done implements TrampolineResult {...}
  • 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); } echo fibonacci(8);
  • 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(); } echo fibonacci(8);
  • 136. What do I miss in PHP7 that Scala luckily has?
  • 137. :) Immutability by default :) Objects cloning :) Options :) Either :)/:( Future :) Parallel collections :) Tail recurrency :( Generic types :( Arrow functions :)/:( Pattern matching / case classes
  • 139. Conclusions ● Don’t be afraid of monads ● Don’t set traps for your team ● Learn Haskell, Clojure, Scala, F#, JavaScript -> TypeScript