SlideShare una empresa de Scribd logo
1 de 141
Descargar para leer sin conexión
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

Más contenido relacionado

La actualidad más candente

Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP GeneratorsMark 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 DICKonstantin Kudryashov
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in actionJace Ju
 
SfCon: Test Driven Development
SfCon: Test Driven DevelopmentSfCon: Test Driven Development
SfCon: Test Driven DevelopmentAugusto 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 itRafael Dohms
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design PatternsHugo Hamon
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHPGuilherme 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 CalisthenicsGuilherme Blanco
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn 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 ApplicationKirill 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.5Leonardo Proietti
 

La actualidad más candente (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
 

Destacado

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.plXSolve
 
Xsolve presentation - programming, bodyleasing, e-commerce
Xsolve presentation - programming, bodyleasing, e-commerceXsolve presentation - programming, bodyleasing, e-commerce
Xsolve presentation - programming, bodyleasing, e-commerceXSolve
 
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 DeliveryXSolve
 
Xlab #2: wzorce projektowe
Xlab #2: wzorce projektoweXlab #2: wzorce projektowe
Xlab #2: wzorce projektoweXSolve
 
xlab #7 - ReactJS & NodeJS
xlab #7 - ReactJS & NodeJSxlab #7 - ReactJS & NodeJS
xlab #7 - ReactJS & NodeJSXSolve
 
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 BootXSolve
 
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 DistribuidaDomingo 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 15Cole Navalazarza
 
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 vidaXimena Sosa Motta
 
firmenkontor24
firmenkontor24firmenkontor24
firmenkontor24infoprimus
 
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.
 
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 gratisNmediaMarketing
 
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, Signaturemi gen
 

Destacado (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 a 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 developersStoyan 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.4Jeff Carouth
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsSam 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 scenariosDivante
 
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 DSLiMasters
 
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
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your CodeAbbas 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 5Stephan 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
 
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 middlewareKuan 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 YieldJason Myers
 

Similar a 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
 

Más de 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 & tricksXSolve
 
How to Create an Agile Office
How to Create an Agile OfficeHow to Create an Agile Office
How to Create an Agile OfficeXSolve
 
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 SpringXSolve
 
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 ChevroletXSolve
 
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 HTTPXSolve
 
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 symfonyXSolve
 
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 guideXSolve
 
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, bodyleasingXSolve
 
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 PRINCE2XSolve
 
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 xdebugXSolve
 
Zarządzanie projektami w XSolve
Zarządzanie projektami w XSolveZarządzanie projektami w XSolve
Zarządzanie projektami w XSolveXSolve
 

Más de 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
 

Último

🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 

Último (20)

🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.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