speakerdeck-june11-fp-pycon2012-gavinbong.pdf

download speakerdeck-june11-fp-pycon2012-gavinbong.pdf

of 47

Transcript of speakerdeck-june11-fp-pycon2012-gavinbong.pdf

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    1/47

    Functional Programmingfor the Uninitiated

    gavin bong

    pycon asia 2012, Singaporele 7 juin 2012 2229 jeudi

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    2/47

    2

    oadmapfunctional wayhigh order functionsrecursion

    foldscurry / partial app.parser combinators

    closing

    30 mins

    mins020208

    08mins06mins03

    mins

    mins

    mins

    min01

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    3/47

    Purely functional is the right

    default. Imperatieconstructs .. must be e!posedthrough e!plicit effects"typing

    constructs.

    #im $weeney%&PI' games (2006)

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    4/47

    *o matter what language you

    wor+ in% programming in afunctional style proidesbenefits. ,ou should do itwheneer it is conenient% andyou should thin+ hard aboutthe decision when it isn-tconenient.

    ohn 'armac+% I $oftware26thapril 2012

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    5/47

    The functional way

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    6/47

    $ide effectf eese immutable containe s.

    ecu sion oe ite ation

    i st"class functions 4 closu es.5ighe "o de functions ee ywhe e

    a7y ealuation

    Functional way: a cook's tour

    Pu efunctions ( efe ential t anspa ency)sin(n), log2(n) 'omposable

    &!ecution order insignificant

    ata t ansfo mations e.g. $#

    etc...

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    7/47

    Is python a functional language?

    anonymous functions (a.+.a lambdas)map% filter% reduceite toolsfunctoolslist comp ehensions%gene ato s

    It is an impe atielanguage that hasac9ui ed some functional featu es.*o

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    8/47

    Functional aspects #1

    Immutable containe s in pythontuplef o7enset

    lambdas in python a e limited to a singlee!p ession.#ypes (has+ell as a efe ence)

    Patte n matching does not e!ist in python.

    nli+e python% has+ell has static typechec+ing with type infe ence.sum :: (Num a) => [a] -> a

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    9/47

    High order functions

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    10/47

    In python 3.!% map etu ns an ite ato .#hus itertools.imapis emoed.

    High order functions

    :ccept functions as a guments and/oetu n functions.map

    map(f, [a, a2]) [f(a), f(a2)]

    filtefilter(predicate, [a, a2]) educeetail t eatment in upcoming slides.

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    11/47

    Functional aspects #2

    [(!, ") for ! in !range(, #)for " in !range(#, )if "-! == $]

    ist comp ehension in python

    [(!, ") % ! &- [..'], " &- [#..], "-! == $]is inspi ed by has+ell;s synta!

    ist comp ehension has la gelysupe ceded the utility of the filter5

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    12/47

    Recursion

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    13/47

    ecu sionunctional languages do *+ntegersum [] =sum (!:!s) =! sum !s

    > has+ell

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    14/47

    defsum(se): ifnotse: return

    else: returnse[] sum(se[:])

    > python

    nave sum function

    #his does not wo + if you pass in anite ato (e.g. gene ato e!p ession) as thea gument. ?e will fi! this in upcomingslides.

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    15/47

    *

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    16/47

    +nteger ->+ntegersum [] acc =accsum (!:!s) acc =sum !s (! acc) > has+ell

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    17/47

    Bany functional languages (li+e $cheme) cansuppo t an unboundednumbe of actie tailcalls ( ecu sie o othe wise).

    5as+ell being a la7y language has adiffe ent app oach.

    tail ecu sion elimination

    defsum(se): deftailsum(se, acc):ifnotse: returnacc else: returntailsum(se[:], se[]acc) returntailsum(se, )

    Python does not perform #ail 'all 4()

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    18/47

    ecu sion in PythonEIn 'Python%

    P efe ite ation oe ecu sion.

    :oid the python stac+.# ampoline techni9ue

    se co e python featu es. e.g.uiltins.sum

    : t ampoline is a function e!ecuto .?o +s fo tail" ecu sie functions(and also co outines with tail"calls).:oids stac+ oe flow.

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    19/47

    Trampolines

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    20/47

    t ampoline >1t*un5 = lamdafn: lamda3args: lamda: fn(3args)

    deftailsum(se, acc): it = iter(se) tr": first, rest = (ne!t(it), list(it)) e!cept 6top+teration: returnacc else: returnt*un5(tailsum)(rest, first acc)

    elayed computation

    #rampoline code is based on e!ample by

    ames #auber FDtauber

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    21/47

    t ampoline >2In python 3.! (see P&P3132)% we can simplifythe code that e!t acts the head 4 tail of theite ato .deftailsum(se, acc): it = iter(se) tr": first, 3rest = it e!cept 7alue1rror: returnacc else: returnt*un5(tailsum)(rest, first acc)

    >python 3

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    22/47

    t ampoline >3deftrampoline(ouncer): *ilecallale(ouncer): 8 s*ould e land "et9 ouncer = ouncer() returnouncer

    defsum(se): returntrampoline(t*un5(tailsum)(se, ))

    #rampoline code is based on e!ample by FDtauber

    bounce

    land

    >>>sum(i fori in range(2))

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    23/47

    t ampoline >G

    # ampoline e sion highly inefficient.

    H8G secs>>>sum( i fori in!range() );'

    'ompa isons of benchma +s using timeit>>>sum( i fori in!range() );'

    1.66 secs

    >>>sum( i fori in!range());'>>sum( i for i in!range());' has+ell

    It encapsulates the ecu sie patte nofp ocessing data st uctu es (listsfo simplicity).

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    26/47

    fold

    sum [] =sum (!:!s) =()!(sum !s) > has+ell

    It encapsulates the ecu sie patte nofp ocessing data st uctu es (listsfo simplicity).

    K2LMraham 5utton N : tutorial on the uniersality 4

    e!pressieness of fold% 1JJJ

    nie salp ope tyK2Lof thef ldope ato g [] =g (!:!s) =f!(g !s) fold f #hus% sumsimplifies to

    relude>foldl () [..$]#

    a ity 2initelists

    It educes a list to a single alue.

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    27/47

    left s ight foldIn has+ell% use foldlfor folding from the left (the

    start) and foldrfor folding from the right (the end).

    relude> let f = (?acc ! -> acc)relude>foldl f [..$];

    &!ample finding the length

    f

    f

    f

    2

    f

    $ left fold

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    28/47

    left s ight fold >2relude> let g = (?! acc -> acc)relude>foldr g [..$];

    &!ample finding the length

    $ g

    g

    2

    g

    g

    ight fold

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    29/47

    fold in pythonIn python 2.!% uiltins.reduce is thepython e sion of the fold ope ato .eft 4 ight folds a e handled by same function.defre@erse(se):

    defr(acc, !): acc.insert(, !) returnacc returnreduce(r, se, [])

    &!ample reerse a list

    et;s implement has+ell;selemusing ight fold.relude>elem 2 [..$]Aruerelude>elem [..$]Balse

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    30/47

    defelem(item, se):

    se = re@erse(se) defmatc*(!, acc): if! == item: returnArue else:

    returnacc returnreduce(lamda a, : matc*(, a), se, Balse)

    &!ample has+ell;selemusing ight fold.

    #he initial alue is set to Balse.#he accumulato emains Balseuntil amatch is found.

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    31/47

    H8G secs>>>sum(i fori in!range() )

    'ompa isons of benchma +s using timeit

    >>> reduce(operator.add,i fori in!range(), )

    1.38msecs

    >>> reduce(operator.add,i fori in!range(), )

    13.6msecsH.HJmsecs

    >>>sum(i for i in!range())

    $imple benchma + of educe>>> importoperator

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    32/47

    In python 3.!% uiltins.reducehasbeen moed to functools.reduce

    $ee al p ope ties of educe

    reduce( lamdaa, : a % , [Arue, Balse, Balse], Balse ) 8 an"

    reducedoes not sho t"ci cuitO which woulde!plain why it is slowe than the builtin an"oallfo use cases below

    reduce( lamdaa, : a C , [Balse, Balse, Arue], Balse ) 8 all

    5omewo +Implement map4 filterusing reduce.

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    33/47

    Currying &

    partial application

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    34/47

    'u ied functions'u yingis the techni9ue of t ansfo ming afunction that ta+es multiplea guments into ..a chain of una yfunctions.&!ample cu ying functions of a ity2>>> importoperator>>> assertoperator.su(, 2)== -operator

    >>> defcurr"2(f): returnlamdaa: lamda: f(a, )

    >>> curriedsu = curr"2(operator.su)>>> assertcurriedsu()(2) ==-

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    35/47

    &!ample uncu ying functions of a ity2uncu y

    >>> defuncurr"2(f): return lamda a, : f(a)()

    >>> originalsu = uncurr"2(curriedsu)

    >>> assertoriginalsu(, 2) ==-

    :ll functions a e cu iedin 5as+ell.K1Lsutract :: (Num a) => a -> a -> a

    as oppose to the uncu iedfo msutract :: (Num a) => (a, a) -> a

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    36/47

    Cenefits of cu ied functions?hat is the point of this E

    #heo etical N able to t eat functions unifo mly.P actical N aids in the c eation of pa tiallyapplied functions.

    Cind somealues to some (but not all) of thea guments of a cu ied function.Pa tial application

    > has+ellg*ci> map (23) [, , 2][, 2, ;]

    g*ci> map (sutract ) [, , 2][-, , ]

    P&P 30J standa di7es a pa tialobDect(since python 2.).

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    37/47

    functools.pa tial in action>>> operator.su.docDsu(a, ) E same as a - .D>>> sutract = partial(operator.su, )>>> sutract(2) 8 e@aluat ng - 2-

    >>> sutract.5e"ordsFG

    >>> sutract.args(,)

    'aeat $ince pe at is a ' module% you cannotbind alues to specific positionala guments.

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    38/47

    functools.pa tial in action >2#he limitation desc ibed in the last slide doesnot apply to use defined functions. #hus%>>> defminus(a, ): Dclone of operator.suD returna - >>> sutract2 = partial(minus, =2)>>> sutract2.5e"ordsFDD: 2G>>> sutract2.docDpartial(func, 3args, 335e"ords) ...D>>> fromfunctools importupdaterapper>>> updaterapper(sutract2, minus)>>> sutract2.docDclone of operator.suD

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    39/47

    miscpa tialcan be applied to classes% classmethods and instance methods.pa tialcan be used to c eate thun+s (asopposed to hand"c afted lambdas)It is o+ to imagine pe at .itemgette 4pe at .att gette as cu ied functions(although thei implementation does notmatch that mental model).

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    40/47

    functools.w apsP o!ying to callables fo c eating deco ato s.

    In conDunction with functools.updateQw appe4 functools.pa tial% the w apped function;sQQnameQQ% QQmoduleQQandQQdocQQa ep ese ed.

    e.g. Dango iew deco ato Fcs fQe!empt

    &!ample deco ato to measu e unning timedefueue(fn, duration): 8 send timings as"nc*ronousl" pass

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    41/47

    importtimefromfunctools importrapsdeftimer(f): Hraps(f) defrapper(3args, 335args): start = time.time() f(3args, 335args) end = time.time() ueue(f.name, end E start) return rapperHtimerdefuserfunction(a, , c): pass

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    42/47

    functools in python 3.!functools.l uQcacheBemoi7ation deco ato that caches esultsof the w appe function.Imp oes pe fo mance of t ee ecu siefunctions e.g. fibonacci.

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    43/47

    Parser combinators:

    a case study

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    44/47

    Pa se combinato s: eal wo ld application of highe o de functions.: pa se is built up f om smalle p imitie pa se s.Pa se combinato s a e Dust highe "o defunctions.

    arser :: 6tring I6AJominator :: arser arser arser#hus% g amma const uction fo things li+eepetition % se9uencing o choice is modelled usingcombinato s.&!ample t iial ma athon unning timepa seusing funcpa selib.

    parse(2:':2')==(2,',2')

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    45/47

    Pa se combinato s >2to5enie: 6tring [Ao5en]

    parse: [Ao5en] tuple

    >>> to5enie(D2:':2'D)[Ao5en(Dositi@e+ntegerD, D2D),Ao5en(DJolonD, D:D),

    Ao5en(Dositi@e+ntegerD, D'D),Ao5en(DJolonD, D:D),Ao5en(Dositi@e+ntegerD, D2'D)]

    >>> parse(to5enie(D2:':2'D))(2, ', 2')

  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    46/47

    Pa se combinato s >3grammar = (*our colon minute colon second s5ip(finis*ed))grammar.parse(se) 8se is [Ao5en]

    'omplete code at http//pastebin.com/+1Bd5$i

    ma5enum = lamdan: int(n)to5@al = lamda!: !.@alue*our = some(lamda !: posint(!) and it*in(!.@alue,K))>> to5@al>> ma5enum

    http://pastebin.com/k1MdUHSihttp://pastebin.com/k1MdUHSi
  • 8/13/2019 speakerdeck-june11-fp-pycon2012-gavinbong.pdf

    47/47

    #he endea ning P will ma+e you a bette(python) p og amme .#heo y$tudy 'atego y theo y4 #ype theo y.

    Play with othe P languages5as+ell%