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
?
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 . ' ';
});
}
(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
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
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-phpapp02Seri Moth
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Developmentjsmith92
 
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 fixturesBill 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. amarilloDani 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
 
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 OOPWildan 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 Applicationselliando 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 aspektowoXSolve
 
Agile estimating and planning
Agile estimating and planningAgile estimating and planning
Agile estimating and planningXSolve
 
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

Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
Elena Simperl
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 

Recently uploaded (20)

Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 

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 ?
  • 18.
  • 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 . ' '; }); }
  • 97.
  • 99. Few rules to make your code functional
  • 100. Do not use :) reassignments :) if :) null :) for :) foreach
  • 102.
  • 103.
  • 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
  • 138.
  • 139. Conclusions ● Don’t be afraid of monads ● Don’t set traps for your team ● Learn Haskell, Clojure, Scala, F#, JavaScript -> TypeScript