Geavanceerde Programmeertechnologie Les 5: Gevorderde Programmeertechnieken Prof. dr. Kris Luyten Jo Vermeulen
Geavanceerde Programmeertechnologie
Les 5: Gevorderde Programmeertechnieken
Prof. dr. Kris Luyten Jo Vermeulen
Doel van deze les
• Programmeerparadigma’s uitdieping • Closures • InspecDe en reflecDe
Uit les 1: Programmeertalen hHp://people.ku.edu/~nkinners/LangList/Extras/classif.htm hHp://oreilly.com/news/graphics/prog_lang_poster.pdf
• Talen: Postscript, Oberon, Tcl/Tk, Fortran, Prolog, Pascal, Delphi, Python, Cobol, Modula, Ada, Rexx, ISO C, C#, Javascript, ANSI/ISO C++, Ruby, Self, Eiffel, PHP, Perl, ML, Lisp, ObjecDve-‐C, VB, Scheme, Haskell, Caml, Smalltalk, Miranda, PL/1, Simula, Java...
• Belangrijkste klassen: imperaDef, funcDoneel, object-‐georiënteerd en logisch
Wat kan je nu?
• ImperaDef programmeren ( C ) • Object-‐georiënteerd programmeren ( C++, Java)
• FuncDoneel programmeren ( Haskell ) • Gebruik van mulD-‐paradigma talen ( Python )
Diepgaand overzicht programmeerparadigma’s
• Programming Paradigms for Dummies: What Every Programmer Should Know, Peter Van Roy, in New Computa?onal Paradigms for Computer Music, G. Assayag and A. Gerzso (eds.), IRCAM/Delatour France, 2009, hBp://www.info.ucl.ac.be/~pvr/paradigms.html
Lezen: secDes 1, 2.1 en 4
!!! niet voor dummies !!!
Peter Van Roy
Figure 1. Languages, paradigms, and concepts
origins in the 1970s. It uses sophisticated algorithms to find solutions that satisfy globalconditions. This means that it genuinely delivers on its ambitious claims.
Conclusions and suggestions for going further Section 8 concludes by reiteratingwhy programming languages should support several paradigms. To understand the“soul”of each paradigm and to gain experience programming with di↵erent paradigms, werecommend the use of a multiparadigm language. A multiparadigm language permitsprogramming in each paradigm without interference from other paradigms. The twomost extensive multiparadigm languages are the dynamically typed language Oz [50]and the statically typed language Alice [38].
2 Languages, paradigms, and concepts
This section gives the big picture of programming paradigms, the languages that realizethem, and the concepts they contain. There are many fewer programming paradigmsthan programming languages. That is why it is interesting to focus on paradigms ratherthan languages. From this viewpoint, such languages as Java, Javascript, C#, Ruby, andPython are all virtually identical: they all implement the object-oriented paradigm withonly minor di↵erences, at least from the vantage point of paradigms.
Figure 1 shows the path from languages to paradigms and concepts. Each program-ming language realizes one or more paradigms. Each paradigm is defined by a set ofprogramming concepts, organized into a simple core language called the paradigm’s ker-nel language. There are a huge number of programming languages, but many fewerparadigms. But there are still a lot of paradigms. This chapter mentions 27 di↵erentparadigms that are actually used. All have good implementations and practical applica-tions. Fortunately, paradigms are not islands: they have a lot in common. We present ataxonomy that shows how paradigms are related.
12
nondeterminism?Observable
Yes No
More declarative Less declarativeNamed stateUnnamed state (seq. or conc.)
(equality)+ name
+ by!need synchronization
+ by!needsynchronization
+ thread
+ continuation
Lazy concurrent
object!orientedConcurrent
programming
Shared!stateconcurrent
programming
Softwaretransactional
memory (STM)
Sequentialobject!orientedprogramming
Statefulfunctional
programming
programmingImperative
Lazydeclarativeconcurrent
programming
programming
Lazydataflow
Concurrentconstraint
programming
constraintprogramming
Constraint (logic)programming
Relational & logicprogramming
Deterministiclogic programming
synchron.+ by!need + thread
+ single assign.
Haskell
Lazyfunctional
programming
Monotonicdataflow
programming
Declarativeconcurrent
programming
ADTfunctional
programming
ADTimperative
programming
Functionalprogramming
First!orderfunctional
programming
Descriptivedeclarative
programming
Imperativesearch
programming
Event!loopprogramming
Multi!agentprogramming
Message!passingconcurrent
programming
Data structures only
Turing equivalent
+ cell (state)
+ unification
Dataflow and
Oz, Alice, Curry Oz, Alice, Curry
CLU, OCaml, Oz
E in one vat
Continuationprogramming
Logic andconstraints message passing Message passing Shared state
v1.08 © 2008 by Peter Van Roy
+ nondeterministic(channel)
Oz, Alice, Curry, Excel,AKL, FGHC, FCP
+ synch. on partial termination
FrTime, SL
+ instantaneous computation
Strong synchronousprogramming
Esterel, Lustre, Signal
Functional reactiveprogramming (FRP)
Weak synchronousprogramming
Pipes, MapReduce
Nondet. state
See "Concepts, Techniques, and Models of Computer Programming".
Explanations
Erlang, AKL
CSP, Occam,E, Oz, Alice,
publish/subscribe,tuple space (Linda)
choice
Nonmonotonicdataflow
programming
Concurrent logicprogramming
Oz, Alice, AKL
+ port
Multi!agentdataflow
programming
The chart classifies programming paradigms according to their kernel
abstractions can be defined). Kernel languages are ordered according tothe creative extension principle: a new concept is added when it cannot beencoded with only local transformations. Two languages that implement
programmer, because they make different choices about whatprogramming techniques and styles to facilitate.
the same paradigm can nevertheless have very different "flavors" for the
languages (the small core language in which all the paradigm’s
without interference from other paradigms. It does not mean that thereis a perfect fit between the language and the paradigm. It is not enoughthat libraries have been written in the language to support the paradigm.The language’s kernel language should support the paradigm. Whenthere is a family of related languages, usually only one member of the family is mentioned to avoid clutter. The absence of a language doesnot imply any kind of value judgment.
When a language is mentioned under a paradigm, it means that part ofthe language is intended (by its designers) to support the paradigm
Typing is not completely orthogonal: it has some effect on expressiveness. Axes orthogonal to this chart are typing, aspects, and domain!specificity.
program’s specification. A domain!specific language should be definablein any paradigm (except when the domain needs a particular concept).
Aspects should be completely orthogonal, since they are part of a
native fashion. This flexibility is not shown in the chart. as Scheme, are flexible enough to implement many paradigms in almosttinkering in particular are orthogonal to this chart. Some languages, such(introspection and reflection). Syntactic extensibility and kernel languageprotocols and generics), to full!fledged tinkering with the kernel language programming combined with syntactic support (e.g., meta!object programming, syntactic extensibility (e.g., macros), to higher!order language. The term covers many different approaches, from higher!order Metaprogramming is another way to increase the expressiveness of a
sequence of values in time. Its expressive power is strongly influenced bythe paradigm that contains it. We distinguish four levels of expressiveness,
State is the ability to remember information, or more precisely, to store a
which differ in whether the state is unnamed or named, deterministic ornondeterministic, and sequential or concurrent. The least expressive isfunctional programming (threaded state, e.g., DCGs and monads:unnamed, deterministic, and sequential). Adding concurrency givesdeclarative concurrent programming (e.g., synchrocells: unnamed,deterministic, and concurrent). Adding nondeterministic choice givesconcurrent logic programming (which uses stream mergers: unnamed,
(e.g., client/server). Named state is important for modularity.
nondeterministic, and concurrent). Adding ports or cells, respectively,gives message passing or shared state (both are named, nondeterministic,and concurrent). Nondeterminism is important for real!world interaction+ local cell
Active objectprogramming
Object!capabilityprogramming
Java, OCaml
+ closure
embeddings
+ solver
LIFE, AKL
CLP, ILOG Solver
+ thread+ single assignment
+ thread
Smalltalk, Oz,
+ thread
Java, Alice
+ log
+ cell(state)
Functional
SQL embeddings
Prolog, SQL
+ search
record
XML,S!expression
The principal programming paradigms"More is not better (or worse) than less, just different."
Haskell, ML, E
(unforgeable constant)
+ cell
Scheme, ML
+ procedure
+ closurePascal, C
SNOBOL, Icon, Prolog
+ search
(channel)+ port
Scheme, ML
Source: hHp://www.info.ucl.ac.be/~pvr/paradigms.html
Eigenschap 1: Observable Nondeterminism
Determinism = er is één en slechts één uitvoering van het programma, waarbij de mogelijke program flows volledig door de ontwikkelaar bepaald worden
Eigenschap 1: Observable Nondeterminism
Nondeterminism = Djdens de programma-‐uitvoering zijn er momenten waarop een systeem (scheduler) kiest wat de volgende stap is uit verscheidene mogelijkheden. De keuze kan niet voorspeld worden.
Eigenschap 1: Observable Nondeterminism
Observable Nondeterminism = de gebruiker (ontwikkelaar) kan zien dat, gegeven eenzelfde startconfiguraDe, de programmauitvoering een verschillend resultaat kan hebben.
Eigenschap 2: Named State
State = de invulling van alle variabelen op opeenvolgende DjdsDppen Djdens de uitvoering van het programma
Eigenschap 2: Named State Programming Paradigms for Dummies
unnamed, deterministic, sequential!
unnamed, deterministic, concurrent!named, deterministic, sequential!
unnamed, nondeterministic, concurrent!named, nondeterministic, sequential!
named, nondeterministic, concurrent!
Declarative paradigms (relational and functional)!
Deterministic concurrency!
Concurrent logic programming!Guarded command programming!
Imperative programming !
Message-passing and shared-state concurrency!
Less!
Expressiveness of state!
More!
Figure 3. Di↵erent levels of support for state
adjacent boxes di↵er in one coordinate.2 One intriguing box shown is Dijkstra’s guardedcommand language (GCL) [14]. It has named state and nondeterministic choice in asequential language. It uses nondeterministic choice to avoid overspecifying algorithms(saying too much about how they should execute).
The paradigms in Figure 2 are classified on a horizontal axis according to how stronglythey support state. This horizontal axis corresponds to the bold line in Figure 3. Let usfollow the line from top to bottom. The least expressive combination is functional pro-gramming (threaded state, e.g., DCGs in Prolog and monads in functional programming:unnamed, deterministic, and sequential). Adding concurrency gives declarative concur-rent programming (e.g., synchrocells: unnamed, deterministic, and concurrent). Addingnondeterministic choice gives concurrent logic programming (which uses stream mergers:unnamed, nondeterministic, and concurrent). Adding ports or cells, respectively, givesmessage passing or shared state (both are named, nondeterministic, and concurrent).Nondeterminism is important for real-world interaction (e.g., client/server). Named stateis important for modularity (see Section 4.4).
Both observable nondeterminism and named state are cases where it is important tochoose a paradigm that is expressive enough, but not too expressive (see epigram at thehead of the chapter). Each of these two concepts is sometimes needed but should be leftout if not needed. The point is to pick a paradigm with just the right concepts. Too fewand programs become complicated. Too many and reasoning becomes complicated. Wewill give many examples of this principle throughout this chapter.
2.2 Computer programming and system design
Figure 4 gives a view of computer programming in the context of general system design.This figure adds computer programming to a diagram taken from Weinberg [56]. Thetwo axes represent the main properties of systems: complexity (the number of basicinteracting components) and randomness (how nondeterministic the system’s behavioris). There are two kinds of systems that are understood by science: aggregates (e.g., gas
2Two of the eight possible combinations are not shown in the figure. We leave it to the reader todiscover them and find out if they make any sense!
15
Eigenschap 3: Record
Datastructuur die verschillende data-‐elementen groepeert en indexeert.
Eigenschap 4: Lexically Scoped Closure
• Een closure is een procedure (funcDe) samen met referen?es buiten de scope van de procedure
Programming Paradigms for Dummies
4 Programming concepts
Programming paradigms are built out of programming concepts. In this section wepresent the four most important programming concepts, namely records, lexically scopedclosures, independence (concurrency), and named state. We explain the concepts andwhy they are important for programming.
4.1 Record
A record is a data structure: a group of references to data items with indexed access toeach item. For example:R=chanson(nom:"Le Roi des Aulnes"
artiste:"Dietrich Fischer-Dieskau"
compositeur:"Franz Schubert"
langue:allemand)
The record is referenced by the identifier R. Members can be references through the dotoperation, e.g., R.nom returns a reference to the string "Le Roi des Aulnes". Therecord is the foundation of symbolic programming. A symbolic programming language isable to calculate with records: create new records, decompose them, and examine them.Many important data structures such as arrays, lists, strings, trees, and hash tables canbe derived from records. When combined with closures (see next section), records canbe used for component-based programming.
4.2 Lexically scoped closure
Definition of procedure P
Context D
Context D
x
state
Call of procedure P
x
Context C
Context C
1. Definition 2. Call
Figure 9. Definition and call of a closure
The lexically scoped closure is an enormously powerful concept that is at the heartof programming. Functional programming, which is programming with closures, is a
23
Eigenschap 4: Lexically Scoped Closure
• FuncDe + “set van” variabelen die in de funcDe gebruikt worden maar niet in de funcDe-‐scope zelf ziHen (niet-‐lokale of vrije variabelen). – Variabelen zijn nodig aan de uitvoering
• Vrije variabelen blijven “geldig” voor de uitvoering van de funcDe.
• Oorspronkelijk voor funcDonele programmeeertalen (Lisp, ML) maar ook in andere paradigma’s.
Closures prakDsch
• Twee toepassingen van closures: – Lambda funcDes (funcDes zonder naam die “inline” uitgevoerd kunnen worden) en anonieme classes.
– FuncDes die funcDes maken en afleveren.
• Een closure zorgt er voor dat de “lokale omgeving” voor de uitvoering van een funcDe volledig is.
Closure in Haskell
• Lambda funcDe
• Closure: variabele x buiten de scope van de funcDe, maar kan toch gebruikt worden
f x = (\y -‐> x + y)
> (\x y -‐> x + y) 3 5 > 8
> map (\x -‐> x + 1) lst
Closure in JavaScript
• Typisch gebruikt voor “generator” funcDes: funcDes die andere funcDes produceren
var createFuncDon = funcDon () { var x = 3; return funcDon () { return 4 + x; }; }; var telop = createFuncDon(); document.write(telop()); // 7
Closure in Python
def counter(): x = 0 def increment(): nonlocal x x += 1 print(x) return increment
counter1_increment = counter() counter2_increment = counter() counter1_increment() # 1 counter1_increment() # 2 counter2_increment() # 1 counter1_increment() # 3
Bron: hHp://en.wikipedia.org/wiki/Closure_(computer_science)
Closure-‐like construcDes in Java: anonymous classes
AcDonListener listener = new AcDonListener() { public void ac?onPerformed(Ac?onEvent ae) { System.out.println("Anonymous"); } }; … myWidget.addAcDonListener(listener);
Closure-‐like construcDes in Java: anonymous classes
myWidget.addAcDonListener(new AcDonListener() { public void ac?onPerformed(Ac?onEvent ae) { System.out.println("Anonymous"); } }; )
Closure-‐like construcDes in Java: anonymous classes
myWidget.addAcDonListener(new AcDonListener() { public void ac?onPerformed(Ac?onEvent ae) { System.out.println("Anonymous"); } }; ) Gedeclareerd en geïnstanDeerd
“ter plekke” Class definiDe zit in de constructor
Closure-‐like construcDes in Java: anonymous classes
public class Magic{ public staDc void main(String[] args) {
Trick t = new Trick(){ public void execute(){ System.out.println(“sim sala bim”); } } t.execute();
} public interface Trick{
void execute(); } }
Closures opdrachten & materiaal • Lesmateriaal: – hHp://www.marDnfowler.com/bliki/Closure.html – Programming Paradigms for Dummies: What Every Programmer Should Know, secDe 4
– Crossing Bordurer: Closures (hHps://www.ibm.com/developerworks/java/library/j-‐cb01097/)
• Opdrachten: zoek twee veel voorkomende redenen om closures te gebruiken – Tip 1: zoek twee situaDes op waarin de code korter en leesbaarder of efficienter wordt door closures te gebruiken.
– Tip 2: Ruby is een programmeertaal waarin closures nu}g gebruikt kunnen worden…
Eigenschap 5: Independence (concurrency)
• Cfr. Processes en threads in OSes
InspecDe en ReflecDe
• Uitvoerbare code die zichzelf kan ondervragen mbt de code structuur
• Dynamische uitvoering van code • Vooral aanwezig bij talen die op een virtual machine werken
• Via een aparte API kan men objecten en classes “ondervragen” – In Java: java.lang.reflect package
ReflecDe in Java
• InspecDe van een object: – Van welke class is dit object? – Van welke classes is dit object afgeleid? – Welke methods biedt het aan? Met welke variabelen?
• Dynamische uitvoering: – Gegeven de naam van een method als een string, invoke deze
– Gegeven de naam van een member variabele als een string, verander de waarde van deze variabele
ReflecDe in Java
• De Class Class hHp://download.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html
• Alle methods om dynamisch klasses te ondervragen en te manipuleren
ReflecDe in Java void printClassName(Object obj) { System.out.println("The class of " + obj + " is " + obj.getClass().getName()); }
Class c = Class.forName(“java.lang.String”);
Class c = int.class;
ReflecDe in Java Class c = Class.forName("java.lang.String"); Method m[] = c.getDeclaredMethods(); for(int i=0; i<m.length; i++)
System.out.println(m[i].toString());
ReflecDe in Java import java.lang.reflect.*; public class constructor2 {
public constructor2() { } public constructor2(int a, int b) { System.out.println( "a = " + a + " b = " + b); }
public staDc void main(String args[]) {
try { Class cls = Class.forName("constructor2"); Class partypes[] = new Class[2]; partypes[0] = Integer.TYPE; partypes[1] = Integer.TYPE; Constructor ct = cls.getConstructor(partypes); Object arglist[] = new Object[2]; arglist[0] = new Integer(37); arglist[1] = new Integer(47); Object retobj = ct.newInstance(arglist); }
catch (Throwable e) { System.err.println(e); } } }
ReflecDe in Java: opdracht • Schrijf een Java programma waar je via de command line een
class name kan ingeven, en die je dan een lijst van methods voor die klasse toont.
>java MethodPrinter Class name? java.lang.Math Fields: public staDc double E public staDc double PI Methods: public staDc double abs(double); Public staDc float abs(float); ….
ReflecDe in Java: opdracht • Schrijf een Java programma dat toelaat via de command line
methods van een arbitraire klasse uit te voeren. Dit hoe� enkel te werken voor classes met een constructor zonder parameters, voor staDc methods of voor staDc classes.
• Na een vraagteken verwacht je programma input • Je tracht de input voor de parameters automaDsch om te zeHen naar
een van de ondersteunde types (volgorde van proberen mag je zelf kiezen). Als geen enkel type lukt stop je met een foutmelding.
• Schrijf het resultaat van de uitvoering van de method naar de output • Schrijf vervolgens ook de waarde van de toString method naar de
output van het gebruikte object (indien het geen staDc class betrof)
ReflecDe in Java: opdracht
>java MethodExecutor What method to invoke? java.lang.StringBuffer.append Needs maximum 3 parameters. How many will you provide? 1 parameter 1? “De kat krrrrabt de krrrrrollen van de trrrrap” Uitvoering gelukt! De kat krrrrabt de krrrrrollen van de trrrrap ….