Functional programming as an alternative (additional) paradigm to - - PowerPoint PPT Presentation

functional programming as
SMART_READER_LITE
LIVE PREVIEW

Functional programming as an alternative (additional) paradigm to - - PowerPoint PPT Presentation

Functional programming as an alternative (additional) paradigm to OOP Mikhail Smal https://mikhail.dev Who are you? http://bonkersworld.net/object-world AbstractToastHeaterGeneratorFactoryInterfaceImplementer


slide-1
SLIDE 1

Functional programming as an alternative (additional) paradigm to OOP

Mikhail Smal https://mikhail.dev

slide-2
SLIDE 2

Who are you?

slide-3
SLIDE 3

http://bonkersworld.net/object-world

slide-4
SLIDE 4

AbstractToastHeaterGeneratorFactoryInterfaceImplementer abstractToastHeaterGeneratorFactoryInterfaceImplementer = new AbstractToastHeaterGeneratorFactoryInterfaceImplementer( AbstractToastHeaterGeneratorFactoryInterfaceImplementer.DEFAULT_PARAMS, 0, NULL);

slide-5
SLIDE 5

Rien n'est plus dangereux qu'une idée, quand on n'a qu'une idée

Émile-Auguste Chartier

slide-6
SLIDE 6

Nothing is more dangerous than an idea, when you have only one idea

Émile-Auguste Chartier

slide-7
SLIDE 7

Nothing is more dangerous than an IDE, when you have only one IDE

slide-8
SLIDE 8

Nothing is more dangerous than an OO, when you have only one

  • bject
slide-9
SLIDE 9

http://bonkersworld.net/object-world

slide-10
SLIDE 10

There are only two hard things in Computer Science: cache invalidation and naming things

Phil Karlton

slide-11
SLIDE 11

It is possible to do Object-Oriented programming in Java

William Cook, "On Understanding Data Abstraction, Revisited"

slide-12
SLIDE 12

public class Ellipse public class Ellipse { public double public double SemiMajorAxis SemiMajorAxis { get; set; } { get; set; } public double public double SemiMinorAxis SemiMinorAxis { get; set; } { get; set; } } public class Circle : Ellipse public class Circle : Ellipse { { public double Radius { get; set; } public double Radius { get; set; } }

slide-13
SLIDE 13

publi blic c c class lass Ell Ellips ipse { publ ublic vi ic virtu rtual al doubl double e Semi emiMajor MajorAxi Axis { get; get; se set; t; } publ ublic vi ic virtu rtual al doubl double e Semi emiMinor MinorAxi Axis { get; get; se set; t; } } publi blic c c class lass Cir Circle cle : El : Ellip lipse se { ... .. publ ublic ov ic overr erride ide doub double le Sem SemiMajo iMajorAx rAxis is { get = get => . > ... .. set = set => t > thro hrow new w new NotSu tSupport pportedE edExce xception ption(); (); } ... ... publ ublic ov ic overr erride ide doub double le Sem SemiMino iMinorAx rAxis is { ... .. }

slide-14
SLIDE 14

publi blic c c class lass Ell Ellips ipse { publ ublic do ic doubl uble e SemiMa emiMajor jorAxi Axis { g { get; et; } } publ ublic do ic doubl uble e SemiMi emiMinor norAxi Axis { g { get; et; } } publ ublic El ic Ellip lipse( se(doubl double e semi emiMajor MajorAxi Axis, doubl double e semi emiMinor MinorAxi Axis) { SemiM SemiMajo ajorAx rAxis is = = sem semiMa iMajorAx jorAxis is; SemiM emiMino norAx Axis = = sem emiMi MinorAx

  • rAxis;

} ... .. } pu publi lic c class ass Cir ircle le { publ ublic do ic doubl uble R e Radius adius { { get get; } ; } publ ublic Ci ic Circl rcle(d e(double

  • uble ra

radiu dius) s) { Radiu Radius = s = ra radius; dius; } publ ublic El ic Ellip lipse se ToEll ToEllips ipse() { { ... .. }

slide-15
SLIDE 15

publi blic c c class lass Ell Ellips ipse { publ ublic do ic doubl uble e SemiMa emiMajor jorAxi Axis { g { get; et; } } publ ublic do ic doubl uble e SemiMi emiMinor norAxi Axis { g { get; et; } } publ ublic El ic Ellip lipse( se(doubl double e semi emiMajor MajorAxi Axis, doubl double e semi emiMinor MinorAxi Axis) { SemiM SemiMajo ajorAx rAxis is = = sem semiMa iMajorAx jorAxis is; SemiM emiMino norAx Axis = = sem emiMi MinorAx

  • rAxis;

} ... .. publ ublic bo ic bool

  • l IsC

IsCircle ircle => .. ... . } pu publi lic c class ass Cir ircle le { publ ublic do ic doubl uble R e Radius adius { { get get; } ; } publ ublic Ci ic Circl rcle(d e(double

  • uble ra

radiu dius) s) { Radiu Radius = s = ra radius; dius; } publ ublic El ic Ellip lipse se ToEll ToEllips ipse() { { ... .. }

slide-16
SLIDE 16

Just because you have a getter, doesn’t mean you should have a matching setter

slide-17
SLIDE 17

public class Ellipse public class Ellipse { public double public double SemiMajorAxis SemiMajorAxis { get; set; } { get; set; } public double public double SemiMinorAxis SemiMinorAxis { get; set; } { get; set; } }

slide-18
SLIDE 18

public class Ellipse public class Ellipse { public double public double SemiMajorAxis SemiMajorAxis { get; } { get; } public double public double SemiMinorAxis SemiMinorAxis { get; } { get; } public Ellipse(double public Ellipse(double semiMajorAxis semiMajorAxis, double , double semiMajorAxis semiMajorAxis) { SemiMajorAxis SemiMajorAxis = = semiMajorAxis semiMajorAxis; SemiMinorAxis SemiMinorAxis = = semiMinorAxis semiMinorAxis; } }

slide-19
SLIDE 19

type Ellipse = type Ellipse = { { SemiMajorAxis SemiMajorAxis : float : float SemiMinorAxis SemiMinorAxis : float } : float } let ellipse = let ellipse = { { SemiMajorAxis SemiMajorAxis = 10. = 10. SemiMinorAxis SemiMinorAxis = 20. } = 20. } let let newEllipse newEllipse = { ellipse with { ellipse with SemiMinorAxis SemiMinorAxis = 30. } = 30. }

slide-20
SLIDE 20

Encapsulation Polymorphism Inheritance

slide-21
SLIDE 21

public public IConnection IConnection CreateConnection CreateConnection(Provider (Provider connectionProvider connectionProvider) { ... ...

slide-22
SLIDE 22

public public Pool

  • oledC

edConnect

  • nnection

ion ConnectT ConnectTo(Pr (Provi

  • vider

er ofU

  • fUpdates

pdates) { ... ...

slide-23
SLIDE 23

Object-oriented Functional vs

slide-24
SLIDE 24

Imperative Declarative vs

slide-25
SLIDE 25

var var numb numbers ers = [1 = [10, 3 0, 3, 7, , 7, 1, 1, 25] 25] num numbers ers.sor sort() ()

slide-26
SLIDE 26

func function tion sor sorted( ted(numb numbers) ers) { { ... ... }

slide-27
SLIDE 27

Excel is the world's most popular functional language

Simon Peyton-Jones

slide-28
SLIDE 28

There is no state in math

slide-29
SLIDE 29

f(x f(x) = = expr xpressi ssion

slide-30
SLIDE 30

In functional programming, programs are executed by evaluating expressions, in contrast with imperative programming where programs are composed of statements which change global state when executed. Functional programming typically avoids using mutable state.

https://wiki.haskell.org/Functional_programming

slide-31
SLIDE 31

Many programming languages support programming in both functional and imperative style but the syntax and facilities

  • f a language are typically optimised for only
  • ne of these styles, and social factors like

coding conventions and libraries often force the programmer towards one of the styles.

https://wiki.haskell.org/Functional_programming

slide-32
SLIDE 32

int int squa square(i re(int x nt x) { { retu return x rn x * x * x; }

slide-33
SLIDE 33

func function tion squ square( are(x) { x) { ret return rn x * * x }

slide-34
SLIDE 34

public class Math public class Math { { public static int Square(int x) public static int Square(int x) { return x * x; return x * x; } }

slide-35
SLIDE 35

squa square(X re(X) ) -> X * X * X. X.

slide-36
SLIDE 36

squa square x re x = x = x * x * x squa square : re :: In : Int t -> > Int Int

slide-37
SLIDE 37

▪do do ▪foreach foreach ▪for for ▪while while

Loops

slide-38
SLIDE 38

fun funct ction ion f fact actor

  • rial

ial(n (n) { ) { var ar re resul sult t = 1 = 1; whil hile e (n (n > > 1) 1) re resul sult t *= *= n--

  • -;

retu eturn rn re resu sult; lt; }

slide-39
SLIDE 39

fun funct ction ion f fact actor

  • rial

ial(n (n) { ) { if ( f (n n > 1 > 1) re retur turn n n * n * f fact actor

  • rial

ial(n (n - 1) 1); else lse re retur turn n 1; 1; }

slide-40
SLIDE 40

fun funct ction ion f fact actor

  • rial

ial(n (n) { ) { retu eturn rn ( ( n n > 1 > 1 ? ? n * n * f fact actor

  • rial

ial(n (n - 1) 1) : : 1); 1); }

slide-41
SLIDE 41

funct function f ion factor actorial(n ial(n) { ) { fun functi ction lo

  • n loop(n,
  • p(n, resu

result) { lt) { re return turn ( ( n > n > 1 1 ? l ? loop(

  • op(n

n - 1, 1, n * n * re resul sult) t) : r : result esult); ); } ret return urn loop loop(n, 1 (n, 1); ); }

slide-42
SLIDE 42

𝒐! = ቊ𝟐, 𝒐 = 𝟏, 𝒐 − 𝟐 ! × 𝒐, 𝒐 > 𝟏.

slide-43
SLIDE 43

𝑜! = ෑ

𝑙=1 𝑜

𝑙

slide-44
SLIDE 44

fac factori

  • rial n

l n = p = produ

  • duct [

t [1..n ..n]

slide-45
SLIDE 45

fac factori

  • rial n

l n = f = foldl ldl (*) (*) 1 [ 1 [1..n ..n]

slide-46
SLIDE 46

f(x f(x) = = λ x • exp express ression ion

slide-47
SLIDE 47

Lambda-calculus was the first object-oriented language (1941)

William Cook, "On Understanding Data Abstraction, Revisited"

slide-48
SLIDE 48

A higher-order function is a function that takes other functions as arguments or returns a function as result.

https://wiki.haskell.org/Higher_order_function

slide-49
SLIDE 49

squa square = re = fun functio ction (x n (x) { ) { ret return rn x * * x; }

slide-50
SLIDE 50

squ square re = x x => x > x * x * x

slide-51
SLIDE 51

squ square re = \x x -> x > x * * x

slide-52
SLIDE 52

map map squa square [ re [1..1 1..100] 00]

slide-53
SLIDE 53

map map (\x x -> x > x * * x) [ ) [1..1 ..100] 0]

slide-54
SLIDE 54

pro product uct = = fo foldr ldr (*) *) 1

slide-55
SLIDE 55

Partial application is the conversion of a polyadic function into a function taking fewer arguments by providing one or more arguments in advance.

http://raganwald.com/2013/03/07/currying-and-partial-application.html

slide-56
SLIDE 56

x x h( ) h( ) g( ) g( ) f( ) f( )

slide-57
SLIDE 57

(f ∙ g ∙ h)(x)

slide-58
SLIDE 58

x x . h h f g

slide-59
SLIDE 59

(f . g . h) x (f . g . h) x

slide-60
SLIDE 60

(f << g << h) x (f << g << h) x

slide-61
SLIDE 61

(h >> g >> f) x (h >> g >> f) x

slide-62
SLIDE 62

library.Select library.Select(book => (book => book.Author book.Author) .Where(author => .Where(author => author.Age author.Age >= 50) >= 50) .Take(15) .Take(15) .Select(author => .Select(author => author.Surname author.Surname) .Select(surname => .Select(surname => surname.ToUpper surname.ToUpper()) ()) .Distinct() .Distinct() .ToList ToList() ()

slide-63
SLIDE 63

$ cat sample.txt | head $ cat sample.txt | head -7 | tail 7 | tail -5

slide-64
SLIDE 64

library library |> |> Seq.map Seq.map (fun b (fun b -> > b.Author b.Author) |> |> Seq.filter Seq.filter (fun a (fun a -> > a.Age a.Age >= 50) >= 50) |> |> Seq.take Seq.take 15 15 |> |> Seq.map Seq.map (fun a (fun a -> > a.Surname a.Surname) |> |> Seq.map Seq.map (fun s (fun s -> > s.ToUpper s.ToUpper()) ()) |> |> Seq.distinct Seq.distinct |> |> List.ofSeq List.ofSeq

slide-65
SLIDE 65

pu public inter blic interface Stack face Stack<T> <T> { int int Dept Depth(); h(); T T T Top();

  • p();

voi void Pop d Pop(); (); voi void Push(T d Push(T newTop ewTop); ); }

slide-66
SLIDE 66

publi blic c c class lass Sta Stack< ck<T> : T> : Abs Abstra tract.St ct.Stack ack<T> <T> { priv private L te List st<T> T> _ite _items s = n new Li w List< t<T>( >(); publ ublic in ic int D t Dept epth() = h() => _ > _ite items.Co ms.Count unt; publ ublic T ic T Top Top() () { if (D if (Dept epth() h() == 0 == 0) thro throw n new w In Inval alidO dOperat eration

  • nExc

xceptio ption(); (); retur return _ n _ite items[De ms[Depth pth() () - 1]; 1]; } publ ublic vo ic void id Pop Pop() () { if (D if (Dept epth() h() == 0 == 0) thro hrow n w new ew Inval validO idOperat peration ionExc Exceptio eption(); (); _item tems.R s.Remo emoveAt veAt(Dep Depth( th() ) - 1); ); } publ public vo c void d Pus ush(T (T newT newTop) { _item tems.A s.Add dd(newTo newTop); ); } }

slide-67
SLIDE 67

pu public inter blic interface Stack face Stack<T> <T> { int int Dept Depth(); h(); T T T Top();

  • p();

Sta Stack<T> ck<T> Pop( Pop(); ); Sta Stack<T> Push ck<T> Push(T (T ne newTop wTop); ); }

slide-68
SLIDE 68

public class public class EmptyStack EmptyStack<T> : <T> : Abstract.Stack Abstract.Stack<T> <T> { public int Depth() => 0; public int Depth() => 0; public T Top() => throw new public T Top() => throw new InvalidOperationException InvalidOperationException(); (); public void Pop() => throw new public void Pop() => throw new InvalidOperationException InvalidOperationException(); (); public void Push(T public void Push(T newTop newTop) => new ) => new NonEmptyStack NonEmptyStack<T>( <T>(newTop newTop, this); , this); }

slide-69
SLIDE 69

pu publ blic i int nterfa face ce Sta tack ck<T> { int t De Depth( h(); ); T To Top( p(); Stac ack< k<T> P Pop

  • p();

Stac ack< k<T> P Pus ush(T T ne newTop

  • p)

) => ne new No NonE nEmpty tySt Stack(ne newTop

  • p,

, this is); ); }

slide-70
SLIDE 70

public class public class EmptyStack EmptyStack<T> : Stack<T> <T> : Stack<T> { public int Depth() => 0; public int Depth() => 0; public T Top() => throw new public T Top() => throw new InvalidOperationException InvalidOperationException(); (); public Stack<T> Pop() => throw new public Stack<T> Pop() => throw new InvalidOperationException InvalidOperationException(); (); }

slide-71
SLIDE 71

public class public class NonEmptyStack NonEmptyStack<T> : Stack<T> <T> : Stack<T> { private T top; private T top; private Stack<T> tail; private Stack<T> tail; public public NonEmptyStack NonEmptyStack(T (T newTop newTop, Stack<T> previous) , Stack<T> previous) { top = top = newTop newTop; tail = previous; tail = previous; } public int Depth() => 1 + public int Depth() => 1 + tail.Depth tail.Depth(); (); public T Top() => top; public T Top() => top; public Stack<T> Pop() => return tail; public Stack<T> Pop() => return tail; }

slide-72
SLIDE 72

va var r stac ack k = ne new w Stac ack< k<stri ring ng>(); ); st stac ack.pu push sh(“Prague”); st stac ack.pu push sh(“Berlin”);

slide-73
SLIDE 73

Stack<string> Stack<string> stack = new stack = new Em EmptyStack ptyStack<string>(); <string>(); stack = stack = stack. stack.push push(“Prague”).push(“Berlin”);

slide-74
SLIDE 74

pu publ blic i int nterfa face ce Sta tack ck<T> { int t De Depth( h(); ); T To Top( p(); Stac ack< k<T> P Pop

  • p();

Stac ack< k<T> P Pus ush(T T ne newTop

  • p)

) => ne new No NonE nEmpty tySt Stack(ne newTop

  • p,

, this is); ); } wh wher ere T T : : immu muta table

slide-75
SLIDE 75

In computing, a persistent data structure is a data structure that always preserves the previous version of itself when it is modified. Such data structures are effectively immutable, as their operations do not (visibly) update the structure in-place, but instead always yield a new updated structure.

https://en.wikipedia.org/wiki/Persistent_data_structure

slide-76
SLIDE 76

a b b = a = a

slide-77
SLIDE 77

a c c = pop = pop(a) (a)

slide-78
SLIDE 78

a c c = pop = pop(a) (a)

slide-79
SLIDE 79

a d d = pus = push(a, h(a, i)

slide-80
SLIDE 80

Concurrency Threads Locks

slide-81
SLIDE 81

All computers wait at the same speed

slide-82
SLIDE 82

Mutable Immutable Unshared Shared Shared mutable data needs synchronization Unshared mutable data needs no synchronization Unshared immutable data needs no synchronization Shared immutable data needs no synchronization

slide-83
SLIDE 83

When it is not necessary to change, it is necessary not to change.

Lucius Cary

slide-84
SLIDE 84

Asking a question should not change the answer.

Bertrand Meyer

slide-85
SLIDE 85

Asking a question should not change the answer, and nor should asking it twice!

slide-86
SLIDE 86

Kevlin Henney

slide-87
SLIDE 87

QUESTIONS

slide-88
SLIDE 88

https://mikhail.dev

Mikhail Smal

Next talk:

Introduction to F# 22 October 2019