59
1 (Func&onal (Programming (in (Scheme)))) Jianguo Lu

(Func&onal (Programming (in (Scheme))))jlu.myweb.cs.uwindsor.ca/440/440scheme2017.pdf · 5 History • Func&onal programming began in the late 1950s. There were many dialects, star&ng

  • Upload
    lyanh

  • View
    218

  • Download
    0

Embed Size (px)

Citation preview

1

(Func&onal(Programming(in(Scheme))))

JianguoLu

2

Programmingparadigms

• Func&onal– Noassignmentstatement

– Nosideeffect– Userecursion

• Logic• OOP• AOP• …

3

Whatisfunc&onalprogramming

• ItisNOTwhatyoudoininIMPERATIVElanguagessuchC,C++,Java,C#....

• Func&onsarefirstclassobjects.– everythingyoucandowith"data"canbedonewithfunc&onsthemselves–  suchaspassingafunc&ontoanotherfunc&on.

– "higherorder"func&ons,func&onsthatoperateonfunc&ons.E.g.,MAP/REDUCE.

• Recursionisusedasaprimarycontrolstructure.– InsomeFPlanguages,noother"loop"constructexists.

• FPisdeclara&ve--worriesaboutwhatistobecomputedratherthanhowitistobecomputed.

FP• ThereisafocusonLIStProcessing.

– Listsareo\enusedwithrecursiononsub-listsasasubs&tuteforloops.

• "Pure"func&onallanguageseschewside-effects.– Nostatements

–  Noassignment–  Nostate–  Noassigningfirstone,thenanothervaluetothesamevariabletotracktheprogramstate.

– oneprogramisoneexpression(plussuppor&ngdefini&ons).

4

5

History

•  Func&onalprogrammingbeganinthelate1950s.Thereweremanydialects,star&ngwithLISP1.5(1960),throughScheme(1975)toCommonLISP(1985).

–  Lisp(1958)àscheme(1975)àcommonLisp(1985)àschemeRRS(1998)–  LISP=LIStProcessor– SchemeissimplerthanLisp

–  Schemespecifica&onisabout50pages,comparedtoCommonLisp's1300pagedra\standard.

•  Anothercategoryoffunc&onalprogramminglanguagesareML(1973)àMiranda(1982)àHaskell(1987).

•  FPISalive– XSLTalsohascharacteris&csoffunc&onalprogramming– MAPREDUCE– Python

•  Themathema&calbasisofmanyfunc&onalprogramminglanguagesisλ-calculus.Itallowsexpressionsthathavefunc&onsasvalues.

6

RunSchemeinterpreterkawa•  kawaisanSchemeinterpreterwrijeninJava•  Alterna&vely,youcanuseotherimplementa&ons.

–  DrSchemeisagoodone.Ithasdetaileddebugginginforma&on.hjp://www.plt-scheme.org/so\ware/drscheme/

•  Downloadkawajarfile–  \p://\p.gnu.org/pub/gnu/kawa/kawa-1.9.90.jar

•  StartKawaby:

C:\440>java-jarkawa-1.9.90.jarkawa.repl

•  TrythefollowingprogramsinKawa

> "hello world"

hello world

> (+ 2 3) 5 >(exit)

•  Alsoinstalledinourschoolunixsystemluna:~>kawa#|kawa:1|#(+23)5

7

Runschemeprogramsinafile

• Insteadofwri&ngeverythingattheSchemeprompt,youcan:– writeyourfunc&ondefini&onsandyourglobalvariabledefini&ons(define...)inafile("file_name")

– attheSchemeprompt,loadthefilewith: (load"file_name")

– attheSchemepromptcallthedesiredfunc&ons

– thereisno"formal"mainfunc&on

8

TheStructureofaSchemeProgram

•  Allprogramsanddataareexpressions

•  Expressionscanbeatomsorlists

•  Atom:number,string,iden&fier,character,boolean– E.g. "hello world" hello world

•  List:sequenceofexpressionsseparatedbyspaces,betweenparentheses– E.g. (+ 2 3)

•  Syntax:expression →atom|listatom →number|string|iden&fier|character|booleanlist →(expr_seq)expr_seq →expressionexpr_seq|expression

9

Interac&ngwithScheme

• Interpreter:"read-eval-print"loop>11

– Reads1,evaluatesit(1evaluatestoitself),thenprintsitsvalue

>(+23)5

+=>func&on+

2=>2

3=>3

Appliesfunc&on+onoperands2and3=>5

10

Evalua&on

• Constantatoms-evaluatetothemselves42 -anumber

3.14-anothernumber

"hello" -astring

‘a‘ -character'a'

#t -booleanvalue"true"

>"helloworld"

helloworld

11

Evalua&onofiden&fiers•  Iden&fiers(symbols)-evaluatetothevalueboundtothem

(definea7)>a7

>(+a5)=>12

>++>x1=>error

12

Evaluatelists

•  Lists-evaluateas"func&oncalls":(func&onarg1arg2arg3...)

•  Firstelementmustevaluatetoafunc&on

•  Recursivelyevaluateeachargument

•  Applythefunc&onontheevaluatedarguments>(-71)

6

>(*(+23)(/62))

15

>

13

Operators

• Prefixnota&on• Anynumberofarguments

>(+)

0

>(+2)

2

>(+23)

5

>(+234)

9

>(-1072)

1

>(/2052)

2

14

Preven&ngEvalua&on(quote)

• Evaluatethefollowing:>(123);Error:ajempttoapplynon-procedure1.

• Usethequotetopreventevalua&on:>(quote(123))

(123)

• Short-handnota&onforquote:>'(123)

(123)

15

Iden&fiersandquotes

(definea7)

a =>7

'a =>a

(+23) =>5

'(+23) =>

(+23)

((+23)) =>

Error

16

Forcingevalua&on

(+123) =>6

'(+123) =>(+123)

(eval'(+123)) =>6

• evalevaluatesitssingleargument

• evalisimplicitlycalledbytheinterpretertoevaluateeachexpressionentered:

“read-eval-print”loop

17

Listopera&ons

• SchemecomesfromLISP,LIStProcessing

• Listopera&ons:cons,car,cdr,…• cons–constructalistfromheadandtail

(cons'a'(bcd)) =>(abcd)

(cons'a'()) =>(a)

(cons'(ab)'(cd)) =>

((ab)cd)

(cons'a(cons'b'())) =>

(ab)

18

Listopera&ons

•  car–returnsfirstmemberofalist(head)(car'(abcd)) =>a(car'(a)) =>a(car'((ab)cd)) => (ab)

(car'(this(isno)moredifficult)) => this

•  cdr–returnsthelistwithoutitsfirstmember(tail)(cdr'(abcd)) =>(bcd)(cdr'(ab)) =>(b)(cdr'(a)) => ()

(cdr'(a(bc))) => (bc)? ((bc))

(car(cdr(cdr'(abcd)))) => c

(car(car'((ab)(cd))))è a

19

listopera&ons•  null?–returns#tifthelistisnull() #fotherwise

(null?()) =>#t

•  list–returnsalistbuiltfromitsarguments(list'a'b'c) =>(abc)(list'a) =>(a)(list'(abc))=> ((abc))

(list'(ab)'c)=> ((ab)c)

(list'(ab)'(cd)) => ((ab)(cd))

(list'(+21)(+21)) => ((+21)3)

20

Listopera&ons

•  length–returnsthelengthofalist(length'(1357)) =>4(length'((ab)c)) => 2

•  reverse–returnsthelistreversed(reverse'(1357)) =>(7531)(reverse'((ab)c)) => (c(ab))

•  append–returnstheconcatena&onofthelistsreceivedasarguments(append'(135)'(79))=>(13579)(append'(a)'()) =>(a)

(append'(ab)'((cd)e)) => (ab(cd)e)

21

TypePredicates

• Checkthetypeoftheargumentandreturn#tor#f(boolean?x) ;isxaboolean?

(char?x) ;isxachar?–  (char?#\a) =>#t–  Charactersarewrijenusingthenota&on#\<character>

(string?x) ;isxastring?(string?“xyx”) =>#t

(number?x) ;isxanumber?(number?2) =>#t

(list?x) ;isxalist?

(procedure?x);isxaprocedure?

(procedure?car)=>#t

22

BooleanExpression

(<12) =>#t

(>=34) =>#f

(=44) =>#t

(eq?22) =>#t

(eq?'(ab)'(ab)) =>#f

(equal?22)=>#t

(equal?'(ab)'(ab)) =>#t;recursivelyequivalent

–  "eq?"returns#tifitsparametersrepresentthesamedataobjectinmemory;

– equal?comparesdatastructuressuchaslists,vectorsandstringstodetermineiftheyhavecongruentstructureandequivalentcontents

(not(>56)) =>#t

(and(<34)(=23)) =>#f

(or(<34)(=23)) =>#t

23

Condi&onalExpressions

•  if–hastheform:(if<test_exp><then_exp><else_exp>)(if(<56)12) =>1

(if(<43)12) =>2

Recallthejavaexpression(x<y)?1:2

•  Anythingotherthan#fistreatedastrue:(if345) =>4

(if'()45) =>4

Itisnotatyped-language

•  ifisaspecialform-evaluatesitsargumentsonlywhenneeded(lazyevalua&on):(if(=34)1(2)) =>Error

(if(=33)1(2)) =>1

24

Condi&onexpression

•  cond–hastheform:(cond(<test_exp1><exp1>...)(<test_exp2><exp2>...)...(else<exp>...))

(definen-5)(cond((<n0)"nega&ve")((>n0)"posi&ve")(else"zero")) =>"nega&ve"

25

Recursivedefini&on

•  HowdoyouTHINKrecursively?•  Example:definefactorial

factorial(n)=1*2*3*...(n-1)*n

factorial(n-1)

1 ifn=1 (thebasecase)

factorial(n)=

n*factorial(n-1) otherwise(induc&vestep)

26

Factorialexample

(define(factorialn)(if(=n1)1(*n(factorial(-n1)))))(factorial4) =>24

27

Fibonacciexample

•  Fibonacci:

0 ifn=0

fib(n)= 1 ifn=1 fib(n-1)+fib(n-2) otherwise

•  ImplementinScheme:(define(fibn)(cond((=n0)0)((=n1)1)(else(+(fib(-n1))(fib(-n2))))))

28

Lengthexample

• Lengthofalist: 0 iflistisempty

len(lst)=

1+len(lst-without-first-element)otherwise

• ImplementinScheme:(define(lenlst)(if(null?lst)0

(+1(len(cdrlst)))))

|(length (a b c d)) | (length (b c d)) | |(length (c d)) | | (length (d)) | | |(length ()) | | |0 | | 1 | |2 | 3

|4

29

Sumexample

•  Sumofelementsinalistofnumbers:(sum‘(123))=>6

0 iflistisempty

sum(lst)=

first-element+sum(lst-without-first-element)otherwise

•  ImplementinScheme:(define(sumlst)

(if(null?lst)0(+(carlst)(sum(cdrlst)))))

30

Memberexample

• Checkmembershipinalist:(define(member?xlst)(cond

((null?lst)#f) ((equal?x(carlst))#t) (else(member?x(cdrlst)))))

31

Recursion

• Whenrecurringonalistlst,– asktwoques&onsaboutit:(null?lst)andelse– makeyourrecursivecallon(cdrlst)

• Whenrecurringonanumbern,– asktwoques&onsaboutit:(=n0)andelse– makeyourrecursivecallon(-n1)

32

Localdefini&on

•  let-hasalistofbindingsandabody– eachbindingassociatesanametoavalue– bindingsarelocal(visibleonlyinthebodyoflet)–  letreturnsthelastexpressioninthebody

>(let((a2)(b3)) ;listofbindings(+ab)) ;body-expressiontoevaluate5

>(+ab) =>error>a =>Error:variableaisnotbound.>b =>Error:variablebisnotbound.

No&cethescopeofaandbiswithinthebodyoflet.

33

Let•  Factoroutcommonsub-expressions:

f(x,y)=x(1+xy)2+y(1-y)+(1+xy)(1-y)a=1+xyb=1-yf(x,y)=xa2+yb+ab

•  Locallydefinethecommonsub-expressions:(define(fxy) (let((a(+1(*xy)))(b(-1y)))(+(*xaa)(*yb)(*ab))))

(f12) =>4

34

‘let’candefinefunc&ons

–  (let((f+))(f23))=>

5

–  (let((f+)(x2))(fx3))=>5

–  (let((f+)(x2)(y3))(fxy))=>

5

•  Thevariablesboundbyletarevisibleonlywithinthebodyofthelet–  (let((+*))(+23))

6(+23)=>

5

35

Inputandoutput

•  read-returnstheinputfromthekeyboard>(read)234 ;usertypesthis234 ;thereadfunc&onreturnsthis>(+2(read))3 ;userinput5 ;result

•  display-printsitssingleparametertothescreen>(display"helloworld")helloworld>(definex2)>(displayx)2

•  newline-displaysanewline

36

Inputandoutput

• Defineafunc&onthatasksforinput:

(define(ask-themstr)(displaystr)

(read))>(ask-them"Howoldareyou?")Howoldareyou?2222

37

InputandOutput

•  Defineafunc&onthatasksforanumber(ifit’snotanumberitkeepsasking):

(define(ask-number)(display"Enteranumber:")(let((n(read)))

(if(number?n) n (ask-number))))

>(ask-number)Enteranumber:aEnteranumber:(56)Enteranumber:"Whydon'tyoulikethese?“Enteranumber:77

38

Interac&vefactorialprogram•  Anouter-levelfunc&ontogowithfactorial,thatreadstheinput,computesthefactorialanddisplaystheresult:

(define(factorial-interac&ve)(display"Enteraninteger:")(let((n(read)))(display"Thefactorialof")(displayn)(display"is")(display(factorialn))(newline)))

>(factorial-interac&ve)Enteraninteger:4Thefactorialof4is24

39

Higherorderfunc&ons

• Afunc&oniscalledahigher-orderfunc&onifittakesafunc&onasaparameter,orreturnsafunc&onasaresult

• InScheme,afunc&onisafirst-classobject–itcanbepassedasanargumenttoanotherfunc&on,itcanbereturnedasaresultfromanotherfunc&on,anditcanbecreateddynamically(let((f+))(f23))

40

Examplesofhigher-orderfunc&ons• map

– Takesasargumentsafunc&onandasequenceoflists– Theremustbeasmanylistsasargumentsofthefunc&on,andlistsmusthavethesamelength

– Appliesthefunc&ononcorrespondingsetsofelementsfromthelists– Returnsalltheresultsinalist

f(E1E2......En)→((fE1)(fE2)......(fEn))

(define(squarex)(*xx))(mapsquare'(12345)) =>(1491625)

–  (mapabs'(1-23-45-6))=>(123456)

– (map+'(123)'(456)) =>(579)

41

lambdaexpression

•  Youcanalsodefinethefunc&onin-place:(map(lambda(x)(*2x))'(123)) =>(246)

–  (map(lambda(xy)(*xy))'(1234)'(8765))=>

(8141820)

•  Asimpleversionofmapdefini&on(define(mapFLst)(if(null?Lst)Lst(cons(F(carLst))(mapF(cdrLst)))))

42

Lambdaexpression

• Alambdaexpression(lambdaabstrac&on)definesafunc&oninScheme.

• Informally,thesyntaxis:(lambda (<parameters>) <body>)

• Forexample:(define addOne (lambda (p) (+ p 1)))

it has the same effect as: (define (addOne p) (+ p 1))

LogoforRacket,afunc&onallanguagebasedonScheme

43

Higherorderfunc&on:reduce(alsocalledfold)

•  F:abinaryopera&on,thatis,atwo-argumentfunc&on.

•  E0:aconstant.•  Wewanttoexpressthefollowingtransforma&on:

(E1E2......En)=>E0FE1FE2F......FEn

•  inschemenota&on:(E1E2......En)=>(FE0(FE1(F......(FEn-1Fn)......)))

(define (reduce F E0 L) (if (null? L) E0 (F (car L) (reduce F E0 (cdr L)))

) )

•  Example: –  (reduce * 1 '(1 2 3 4)) –  è 1*1*2*3*4

44

exercise:whatistheresultofthisexpression?

(reduce+0(map(lambda(x)1)‘(123)))

Differentwaystodefinelengthfunc&on(define(lenlst)(if(null?lst)0(+1(len(cdrlst)))))

(definelen(lambda(lst)(if(null?lst)0(+1(len(cdrlst))))))(definelen(lambda(lst)(reduce+0(map(lambda(x)1)lst))))

45

Higherorderfunc&on:apply

• apply– takesafunc&onandalist– theremustbeasmanyelementsinthelistasargumentsofthefunc&on

– appliesthefunc&onwiththeelementsinthelistasarguments(apply*'(56)) =>30(applyappend'((ab)(cd)))=>(abcd)

• Comparisontoeval:(eval<expression>)or(eval(<func><arg1><arg2>...))

(apply<func>(<arg1><arg2>...))

46

Higherorderfunc&on:compose

• Composetakestwofunc&onsasparameters.

• Italsoreturnsafunc&on(define(composefg)(lambda(x) (f(gx))))

((composecarcdr)'(123))=>

2

((compose(lambda(x)(+1x))(lambda(x)(*2x)))5)=>11

47

Definereversefunc&on

(definereverse(lambda(L)

(if(null?L)

'()

(append(reverse(cdrL))(list(carL))))))

48

> ( define ( append L1 L2 ) ; built-in! (if ( null? L1 ) L2 ( cons ( car L1 ) ( append ( cdr L1 ) L2 ) ) ) )

> ( append '( ab bc cd ) '( de ef fg gh ) ) => (ab bc cd de ef fg gh)

Appendexample

49

> ( define ( numberList? x ) ( cond ( ( not ( list? x ) ) #f ) ( ( null? x ) #t ) ( ( not ( number? ( car x ) ) ) #f ) ( else ( numberList? ( cdr x ) ) ) ) ) > ( numberList? ' ( 1 2 3 4 ) ) #t > ( numberList? ' ( 1 2 3 bad 4 ) ) #f

Numberlistexample

50

Inser&onsortexample

(define(insertxl)

(if(null?l)

(listx)

(if(<=x(carl))

(consxl)

(cons(carl)(insertx(cdrl))))))

(define(isortl)

(if(null?l)

()

(insert(carl)(isort(cdrl)))))

Inser&onsortinanimpera&velanguagevoidisort(int[]A){

intj;

for(inti=1;i<A.length;i++){

inta=A[i];

for(j=i-1;j>=0&&A[j]>a;j--)

A[j+1]=A[j];

A[j+1]=a;

}

}

DFAsimula&on

• Startstate:q0• Transi&ons

((q00)q2)((q01)q1)((q10)q3)((q11)q0)

((q20)q0)((q21)q3)((q30)q1)((q31)q2)

• Finalstate:q0• DFA

'(q0

(((q00)q2)((q01)q1)((q10)q3)((q11)q0)

((q20)q0)((q21)q3)((q30)q1)((q31)q2))

(q0))

51

Definemovefunc&on

52

(definemove

(lambda(dfasymbol)

(let((curstate(cardfa))(trans(cadrdfa))

(finals(caddrdfa)))

(list

(if(eq?curstate'error) ;getthenextstateor‘error

'error

(let((pair(assoc(listcurstatesymbol)trans)))

;pairisthenextstate,say((q0,0),q2),orfalsewhennotfound

(ifpair(cadrpair)'error)));booleancondistrueifnotfalse

trans

finals))))

•  cadr:carandcdr.Secondelement

•  caddr:thirdelement

•  assoc:searchanelementinanassocia&onlist

'(q0

(((q00)q2)((q01)q1)((q10)q3)((q11)q0)

((q20)q0)((q21)q3)((q30)q1)((q31)q2))

(q0))

assocfunc&on

• assoc:searchanassocia&onlist(table)– Anassocia&onlistisalistoflists.– Eachsublistrepresentsanassocia&onbetweenakeyandalistofvalues.

• Examples–  Scheme>(assoc'julie'((paulaugust22)(juliefeb9)(veroniquemarch28)))

–  (juliefeb9)

– Scheme>(assoc'key2'((key1val1)(key2val2)(key0val0)))–  (key2val2)

– Scheme>(assoc'(feb9)'(((aug1)maggiephil)((feb9)jimheloise)((jan6)declan)))

–  ((feb9)jimheloise)

–  (assoc(listcurstatesymbol)trans)

–  (assoc‘(q00)trans)à((q0,0),q2)

53

Simulatefunc&on

(definesimulate

(lambda(dfainput)

(cons(cardfa)

(if(null?input)

(if(infinal?dfa)'(accept)'(reject))

(simulate(movedfa(carinput))(cdrinput))))))

•  Runtheprogram(simulate

'(q0

(((q00)q2)((q01)q1)((q10)q3)((q11)q0)

((q20)q0)((q21)q3)((q30)q1)((q31)q2))

(q0))

'(010010))

•  Output:thetraceofthestatesand‘accept’or‘reject’(q0q2q3q1q3q2q0accept)

54

infinalstatefunc&on(defineinfinal?

(lambda(dfa)

(memq(cardfa)(caddrdfa))))

•  dfa'(q0

(((q00)q2)((q01)q1)((q10)q3)((q11)q0)

((q20)q0)((q21)q3)((q30)q1)((q31)q2))

(q0))

• memq:returnthefirstsublistoflistwhosecarisobj.Ifobjdoesnotoccurinlist,then#f(nottheemptylist)isreturned

– memq'a'(abc))==>(abc)

–  (memq'b'(abc))==>(bc)

–  (memq'a'(bcd))==>#f

55

56

Assignment

• acalculatorforsimplearithme&cexpressions– whentyping(calculator'(1+2)),schemeinterpreterwillprint3.

• Thecalculatorwillacceptexpressionofanylength,andtheexpressionassociatestotheright.

– In(calculator'(1+1-2+3)),theexpressionisinterpretedas(1+(1-(2+3))),hencethevalueis-3.

• Onebonusmarkforle\associa&on1+1-2+3isevaluatedas3

57

Interpreterandcompiler

• Interpreter– Programisexecuteddirectly.Notranslatedcodeisgenerated.

– Slow– Forsmallprograms

• Compiler– Programistranslatedintocodethatisclosertomachine(intermediatecode,orassemblycode,ormachinecode)

– Faster– Forbiggerprograms

– hybridimplementa&onforJavaandC#

58

Func&onalprogramming

• Pythorn• XSLT• MAPREDUCE

59

Moreaboutassignment(defineexpr'(+12))

(evalexpr)

(defineoperator(carexpr))

operator

(operator23)–  +–  procedureapplica&on:expectedprocedure,given:+

(defineoperator(eval(carexpr)))

operator

(operator23)–  #<procedure:+>–  5