Upload
david-de-boer
View
598
Download
1
Embed Size (px)
Citation preview
– Robert C. Martin
“There is a freight train barreling down the tracks towards us, with multi-core emblazoned on it; and you’d better be ready by the time it gets here.”
λ
closures
__invoke
2001 2009 2011 2012
array_map
array_filter
callable
Slim
Silex
middlewares Symfony2
I’m David
/ddeboer
@ddeboer_nl
Let’s begin$ brew install erlang
$ erl
Erlang/OTP 18 [erts-7.2.1] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Eshell V7.2.1 (abort with ^G)1>
on OS X
REPL
-module(math).-export([sum/1]).
sum(Number) -> Sum = 0, Numbers = lists:seq(1, Number),
lists:foreach( fun(N) -> Sum = Sum + N end, Numbers ), Sum.
math:sum(5).
no return keyword
** exception error: no match of right hand side value 1
1> X = 5.52> X.53> X = X * 2.** exception error: no match of right hand side value 104> 5 = 10.** exception error: no match of right hand side value 10
but isn’t
looks like assignment
-module(math2).-export([sum2/1]).
sum2(Number) -> List = lists:seq(1, Number), sum2(List, 0).
sum2([], Sum) -> Sum;sum2([H|T], Sum) -> sum2(T, H + Sum).
3> math2:sum(5).15
empty list
separate head from tail recurse
pattern matches
generate list
Declarative 1<?php
// Declare a function!function sum($x){ if ($x == 0) { return $x; }
return $x + sum($x - 1);}
sum(5);// still 15
$x never changes
recursion
Declarative 2<?php
function sum2($number){
array_sum(range(1, $number));}
echo sum2(5);// yuuuup, 15 again
functionfunction
composition
A lot of our code is about the
hardware it runs on
But programmers should worry about the conceptual problem domain
Recursion-module(math).-export([fac/1]).
fac(0) -> 1;fac(N) -> N * fac(N - 1).
1> math:fac(9).362880
Recursion fail-module(math).-export([fac/1]).
fac(0) -> 1;fac(N) -> N * fac(N - 1).
%%fac(9) = 9 * fac(9 - 1)%% = 9 * 8 * fac(8 - 1)%% = 9 * 8 * 7 * fac(7 - 1)%% = 9 * 8 * 7 * 6 * fac(6 - 1)%% = 9 * 8 * 7 * 6 * 5 * fac(5 -1)%% = 9 * 8 * 7 * 6 * 5 * 4 * fac(4 - 1)%% = 9 * 8 * 7 * 6 * 5 * 4 * 3 * fac(3 - 1)%% = 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * fac(2 - 1)%% = 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 * fac(1 - 1)%% = 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 * 1%% = 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1%% = 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2%% = 9 * 8 * 7 * 6 * 5 * 4 * 6%% = 9 * 8 * 7 * 6 * 5 * 24%% = 9 * 8 * 7 * 6 * 120%% = 9 * 8 * 7 * 720%% = 9 * 8 * 5040%% = 9 * 40320%% = 362880
10 terms in memory
Tail recursion-module(math).-export([tail_fac/1]).
tail_fac(N) -> tail_fac(N, 1).
tail_fac(0, Acc) -> Acc;tail_fac(N, Acc) -> tail_fac(N - 1, N * Acc).
tail_fac(9) = tail_fac(9, 1).tail_fac(9, 1) = tail_fac(9 - 1, 9 * 1).tail_fac(8, 9) = tail_fac(8 - 1, 8 * 9).tail_fac(7, 72) = tail_fac(7 - 1, 7 * 72).tail_fac(6, 504) = tail_fac(6 - 1, 6 * 504).tail_fac(5, 3024) = tail_fac(5 - 1, 5 * 3024).…tail_fac(0, 362880) = 362880
do calculation before recursing
$object->setFoo(5);
$value = $object->getFoo();
$object->setFoo('Change of state!');
$value = $object->getFoo();
no return value
no input value
same argument, different return value
No side-effects
A pure function
does not rely on data outside itself
does not change data outside itself
Object orientation
Solve problems with objects
Objects have internal state
Modify state through methods
With side-effectsclass Todo{
public $status = 'todo';}
function finish(Todo $task){
$task->status = 'done';}
$uhoh = new Todo();$uhoh2 = $uhoh;
finish($uhoh);
echo $uhoh->status; // doneecho $uhoh2->status; // done???
No side-effectsclass Todo{
public $status = 'todo';}
function finish(Todo $task){
$copy = clone $task;$copy->status = 'done';
return $copy;}
$uhoh = new Todo();$finished = finish($uhoh);
echo $finished->status; // doneecho $uhoh->status; // todo
cloning is cheap
$names = ['Billy', 'Bob', 'Thornton'];
$anonymise = anonymise('sha256');
var_dump(array_map($anonymise, $names));// array(3) {// [0]=>// string(64) "85eea4a0285dcb11cceb68f39df10d1aa132567dec49b980345142f09f4cb05e"// [1]=>// string(64) "cd9fb1e148ccd8442e5aa74904cc73bf6fb54d1d54d333bd596aa9bb4bb4e961"// [2]=>// string(64) "d7034215823c40c12ec0c7aaff96db94a0e3d9b176f68296eb9d4ca7195c958e"// }
using PHP built-ins
$names = ['Billy', 'Bob', 'Thornton'];
$anonymise = anonymise('sha256');
var_dump(array_map($anonymise, $names));// array(3) {// [0]=>// string(64) "85eea4a0285dcb11cceb68f39df10d1aa132567dec49b980345142f09f4cb05e"// [1]=>// string(64) "cd9fb1e148ccd8442e5aa74904cc73bf6fb54d1d54d333bd596aa9bb4bb4e961"// [2]=>// string(64) "d7034215823c40c12ec0c7aaff96db94a0e3d9b176f68296eb9d4ca7195c958e"// }
function anonymise($algorithm){ return function ($value) use ($algorithm) { return hash($algorithm, $value); };}
higher-order function
closure
using PHP built-ins
function as value
function as argument
Middleware<?php
use Psr\Http\Message\RequestInterface;
function add_header($header, $value){ return function (callable $handler) use ($header, $value) { return function ( RequestInterface $request, array $options ) use ($handler, $header, $value) { $request = $request->withHeader($header, $value);
return $handler($request, $options); }; };}
$myStack = (new MiddlewareStack())->push(add_header('Silly-Header', 'and its value'));
call next in stack
immutable
higher-order function
Middleware<?php
use Psr\Http\Message\ServerRequestInterface as Request;use Psr\Http\Message\ResponseInterface as Response;
$app = new \Slim\App();
$app->add(function (Request $request, Response $response, callable $next) { $response->getBody()->write('Hey there, '); $response = $next($request, $response); $response->getBody()->write('up?');
return $response;});
$app->get('/', function ($request, $response, $args) { $response->getBody()->write('what’s');
return $response;});
$app->run();// Hey there, what’s up?
stream is not immutable
before
after
Service objects<?php
namespace Symfony\Component\Security\Core;
interface SecurityContextInterface{ public function getToken(); public function isGranted($attributes, $object = null);}
Service objects<?php
namespace Symfony\Component\Security\Core\Authentication\Token\Storage;
interface TokenStorageInterface{ public function getToken();}
namespace Symfony\Component\Security\Core\Authorization;
interface AuthorizationCheckerInterface{ public function isGranted($attributes, $object = null);}
single function
More?