### La programmation fonctionnelle

#### pour les développeuses·eurs web

@ThibaudDauce | https://thibaud.dauce.fr

#### Co-fondateur de Quantic Telecom

https://www.quantic-telecom.net

#### Formations Laravel

https://www.formations-laravel.fr

### La programmation fonctionnelle

#### pour les développeuses·eurs web

@ThibaudDauce | https://thibaud.dauce.fr

### Euh… J'en fais déjà, non ?

                        // Get invoices
                        $api = new API()
                        $result = $api->post('/invoices', []);
                        $invoices = json_decode($result);

                        // Get students
                        $customers = Customer::all();
                        $students = [];
                        foreach ($customers as $customer) {
                            if ($customer->isStudent()) {
                                $students[] = $customer;
                            }
                        }

### Euh… J'en fais déjà, non ?

                        // Get invoices
                        $invoices = getInvoices();

                        // Get students
                        $students = getStudents();

### Votre serveur web est une fonction

#### Requête HTTP → Réponse HTTP

                    // 1. Vérifiez que la personne est connectée
                    // 2. Enregistrer le début du traitement de la requête
                    // 3. Faire ce que tu as à faire
                    //    (retourne une chaîne de caractères)
                    // 4. Transformer la chaîne de caractères en réponse HTTP
                    // 5. Enregistrer le temps de traitement grâce à 2.

                    $tasks = [
                        new CheckAuthentication,
                        new LogRequestTime,
                        new TransformToResponse,
                    ];

### Pipelines / Middlewares

                        (new Pipeline)
                            ->send(Request::createFromGlobals())
                            ->through([
                                new CheckAuthentication,
                                new LogRequestTime,
                                new TransformToResponse,
                            ])
                            ->then(function ($request) {
                                return "Welcome {$request->session('customer')}!";
                            });

                        class CheckAuthentication
                        {
                            public function handle($request, $next)
                            {
                                if (! $request->session()->has('customer')) {
                                    return new RedirecResponse('/login', 302);
                                }

                                return $next($request);
                            }
                        }

                        class LogRequestTime
                        {
                            public function handle($request, $next)
                            {
                                $start = microtime(true);

                                $response = $next($request);

                                $time = microtime(true) - $start;
                                $text = "Request {$request->requestUri} took {$time}s \n";
                                file_put_content('timings.txt', $text, FILE_APPEND);

                                return $response;
                            }
                        }

                        class TransformToResponse
                        {
                            public function handle($request, $next)
                            {
                                $response = $next($request);

                                if ($response instanceof Response) {
                                    return $response;
                                }

                                return new Response((string) $response, 200);
                            }
                        }

                        function ($request) {
                            return "Welcome {$request->session('customer')}!";
                        }

### Votre serveur web est une fonction

#### (Le retour)

1. Requête HTTP → Identifiant client
2. Identifiant client → Client
3. Client → Total des comptes
4. Total des comptes → Page HTML
5. Page HTML → Réponse

### Collections

                        function getMonthlyMeanRevenueForStudents() {
                            $customers = Customer::all();
                            $totalRevenue = [];
                            $counts = [];

                            foreach($customers as $customer) {
                                if ($customer->isStudent()) {
                                    foreach($customer->invoices() as $invoice) {
                                        $totalRevenue[$invoice->month()] +=
                                            $invoice->total();
                                        $counts[$invoice->month()]++;
                                    }
                                }
                            }

                            $meanRevenue = [];

                            foreach ($revenues as $month => $total) {
                                $meanRevenue[$month] = $totalRevenue[$month] / $counts[$month];
                            }

                            return $meanRevenue;
                        }

### Collections

                    function getMonthlyMeanRevenueForStudents() {
                        return Customer::all()
                            // [
                            //     'Étudiant John',
                            //     'Étudiante Jane',
                            //     'Entreprise Google',
                            // ]
                            ->filter(function ($customer) {
                                return $customer->isStudent();
                            })
                            // [
                            //     'Étudiant John',
                            //     'Étudiante Jane',
                            // ]
                            ->map(function ($customer) {
                                return $customer->invoices();
                            })
                            // [
                            //     ['2017-07-001', '2017-08-001'],
                            //     ['2017-07-002'],
                            // ]
                            ->flatten()
                            // [ '2017-07-001', '2017-08-001', '2017-07-002' ]
                            ->groupBy(function ($invoice) {
                                return $invoice->month();
                            })
                            // [
                            //     '2017-07' => ['2017-07-001', '2017-07-002'],
                            //     '2017-08' => ['2017-08-001'],
                            // ]
                            ->map(function ($invoices) {
                                // = ['2017-07-001', '2017-07-002']// = [80, 100]// = 180// = 90
                                return $invoices->map(function ($invoice) {
                                    return $invoice->total();
                                })->sum() / $invoices->count();
                            });

                            // [
                            //     '2017-07' => 90,
                            //     '2017-08' => 150,
                            // ]
                    }

### Collections

                    function getMonthlyMeanRevenueForStudents() {
                        return Customer::all()
                            ->filter->isStudent()
                            ->flatMap->invoices()
                            ->groupBy->month()
                            ->map(function ($invoices) {
                                return $invoices->map->total()->sum() / $invoices->count();
                            });
                    }

### Un peu de Front-End

#### Elm

### MVU

#### Model View Update

### Model

                        type alias Model = String

                        init : Model
                        init = ""

### Update

                        type Event = Typed String

                        update : Event -> Model -> Model
                        update (Typed textTyped) oldTextTyped = textTyped

### View

                        view : Model -> Html Event
                        view textTyped =
                        div []
                            [ input [ placeholder "Text to reverse", onInput Typed ] []
                            , div [] [ text (String.reverse textTyped) ]
                            ]

### elm-lang.org

### D'autres ressources

- Understanding Laravel Pipelines
- Refactoring to Collection
- Haskell Book
- PureScript
- Learn PureScript by Example

### Merci à tous

@ThibaudDauce | https://thibaud.dauce.fr