Functional OO
Programming
Prof. Dr. Ralf Lämmel
Universität Koblenz-Landau
Software Languages Team
Let’s say we know OOP.
What’s functional programming?
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Functional programming focuses on
funct...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Encoding functions as instance methods
...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
public class TrivialExample {
public st...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
evaluate :: Expr -> Int
evaluate (Lit i...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Instance-of-based pattern matching
publ...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
filter is a higher-order function!
-- Qu...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
We iterate the increment function forev...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Hence:
• Optimizations can be more aggr...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
(define (memoize f)
(let ((table (make-...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
The notion of closure
Wikipedia as of 4...
What’s functional OO
programming (in Java 7)?
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Functional OO Programming
in Java 7
Rel...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Nested classes in Java
class OuterClass...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Anonymous classes
cutButton.addActionLi...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Closures in Java
In Java (7), we may eq...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Listeners in a GUI
DEMO
cutButton.addAc...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Function objects
Wikipedia as of 4 June...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Sample of a functor interface
/**
* Fun...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Sample of a functor implementation
twic...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Issues with Java <= 7 functors
Only fun...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Further reading
• John Hughes: Why Func...
Major use case for FOOP:
Combinator libraries
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
The notion of
combinator library
Wikipe...
Traversal
combinators
http://101companies.org/wiki/
Contribution:javaSyb
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Motivation of
traversal combinators
pub...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Motivation of
traversal combinators
pub...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
The paradigm of using
traversal combina...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Problem-specific transformation
function...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Problem-specific query
functionality for...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Combine type-specific transformation
wit...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Combine type-specific query with
constan...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Apply traversal scheme for
transformati...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Apply traversal scheme for query
public...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
The traversal scheme
everywhere
public ...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
The traversal scheme
everywhere
public ...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
The traversal scheme
everything
public ...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
The traversal scheme
everything
public ...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Traversal of companies
DEMO
http://101c...
Parser
combinators
http://101companies.org/wiki/
Contribution:javaParseLib
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
	 void department() {
	 	 match(DEPARTM...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
The paradigm of using
parser combinator...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
The types of
acceptors and parsers
publ...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
An acceptor combinator for “*”
public c...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
An acceptor combinator for “*”
public c...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
	 public static Acceptor star(final Acc...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
public class Star<T> extends Parser<Lis...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
public class Star<T> extends Parser<Lis...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
EBNF of 101companies
company :
'company...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Nonterminals as static fields
	 public s...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Nonterminals as methods
	 public static...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Parsing comapanies
DEMO
http://101compa...
(C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable)
Summary
Functional OOP really combines ...
Upcoming SlideShare
Loading in …5
×

Functional OO programming (as part of the the PTT lecture)

885 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
885
On SlideShare
0
From Embeds
0
Number of Embeds
323
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Functional OO programming (as part of the the PTT lecture)

  1. 1. Functional OO Programming Prof. Dr. Ralf Lämmel Universität Koblenz-Landau Software Languages Team
  2. 2. Let’s say we know OOP. What’s functional programming?
  3. 3. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Functional programming focuses on functions as abstractions (as in math). -- Two functions only requiring zero, succ, pred add n m = if (n==0) then m else (add (n-1) m) + 1 mult n m = if (n==0) then 0 else add (mult (n-1) m) m Functions are perfectly well-defined mathematical entities. Making us think of the above functions as objects isn’t that helpful. Haskell
  4. 4. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Encoding functions as instance methods To be void or to return? Why to tie a function to the class for the 1st argument? public class “int” { public int add(int m) { return (this==0) ? m : (this-1).add(m)+1; } public int mult(int m) { return (this==0) ? 0 : (this-1).mult(m). add(m); } }
  5. 5. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) public class TrivialExample { public static int add(int n, int m) { return (n==0) ? m : add(n-1,m)+1; } public static int mult(int n, int m) { return (n==0) ? 0 : add(mult(n-1,m),m); } } What’s the purpose of classes here? There is some boilerplate code. Encoding functions as static methods
  6. 6. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) evaluate :: Expr -> Int evaluate (Lit i) = i evaluate (Add l r) = evaluate l + evaluate r Remember the expression problem! Virtual functions scatter the code over classes. Haskell Functional programming supports case discrimination.
  7. 7. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Instance-of-based pattern matching public static int Evaluate(Expr e) { if (e instanceof Lit) { Lit l = (Lit)e; return l.info; } if (e instanceof Add) { Add a = (Add)e; return Evaluate(a.left) + Evaluate(a.right); } throw new IllegalArgumentException(); } Very little type checking! Proper functional OO programming instances to the rescue.
  8. 8. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) filter is a higher-order function! -- QuickSort in Haskell quicksort [] = [] quicksort [e] = [e] quicksort unsorted = quicksort lt ++ eq ++ quicksort gt where pivot = head unsorted lt = filter (<pivot) unsorted eq = filter (==pivot) unsorted gt = filter (>pivot) unsorted Haskell Functional programming encourages composition of functionality via higher-order functions.
  9. 9. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) We iterate the increment function forever. However, we only take the first 5 elements of the stream. > take 5 (iterate (1+) 0) [0,1,2,3,4] Haskell Functional programming supports (in some instances) lazy evaluation.
  10. 10. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Hence: • Optimizations can be more aggressive. • Parallelization is feasible more often. • Transactions in memory are more manageable. • Proofs of program correctness rely on referential transparency. Functional programming encourages pure functions.
  11. 11. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) (define (memoize f) (let ((table (make-table))) (lambda (x) (let ((previously-computed-result (lookup x table))) (if (not (null? previously-computed-result)) previously-computed-result (let ((result (f x))) (insert! x result table) result)))))) A memoization function as of Brian Goetz: Java theory and practice: The closures debate, 2007, IBM developerWorks. The combinator takes a function and returns a function. It interleaves imperative actions with normal function application. Scheme Functional programming supports composition of closures.
  12. 12. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) The notion of closure Wikipedia as of 4 June 2013: In computer science, a closure (also lexical closure or function closure) is a function or reference to a function together with a referencing environment—a table storing a reference to each of the non- local variables (also called free variables) of that function. [...] The concept of closures was developed in the 1960s and was first fully implemented in 1975 [...] as a language feature in the Scheme programming language to support lexically scoped first-class functions.
  13. 13. What’s functional OO programming (in Java 7)?
  14. 14. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Functional OO Programming in Java 7 Relevant Java concepts Nested classes Anonymous classes Function objects (functors) Riddles Can we do filter in Java 7 (or C#)? Can we be lazy in Java 7 (or C#)? Can we do memoization in Java 7 (or C#)?
  15. 15. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Nested classes in Java class OuterClass { ! ... ! class NestedClass { ... } ! ... } • Nested classes can be class members. • Nested classes can be declared locally in a method. • Non-static nested classes have access to outer scope. • Why use nested classes? – Group classes that are only used in one place. – Nested scopes – simulate closures.
  16. 16. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Anonymous classes cutButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { controller.cutEmployeeClicked(); } }); • These are nested classes w/o a name. • They are derived from an interface or base class. • Members are declared as part of construction. • Free names occur inside the constructor. A closure
  17. 17. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Closures in Java In Java (7), we may equate the notion of an anonymous class with (a restricted form of) the general notion of closure. For such a closure to be “nontrivial” (in the sense that the anonymous class cannot be trivially eliminated), the anonymous class should reference “variables” outside the immediate scope of the anonymous class. For instance, there could be references to the arguments of the enclosing method, or to temporary variables, or to fields of the hosting object. (By the language rules, the variables are all “final”.)
  18. 18. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Listeners in a GUI DEMO cutButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { controller.cutEmployeeClicked(); } }); 101implementation:swing
  19. 19. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Function objects Wikipedia as of 4 June 2013: “A function object [...] is a computer programming construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax (a function parameter that can also be a function).”
  20. 20. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Sample of a functor interface /** * Functions with 1 argument */ public interface UnaryFunction<X,Y> { public Y apply(X x); }
  21. 21. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Sample of a functor implementation twice( new UnaryFunction<Integer,Integer>(){ public Integer apply(Integer x) { return ++x; } }, 40 ) Exercise: suppose this expression is supposed to compute 42 because twice applies the argument twice. What’s the definition of twice?
  22. 22. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Issues with Java <= 7 functors Only function objects – no functions. Verbose creation of closures. No access to non-final variables in outer scope.
  23. 23. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Further reading • John Hughes: Why Functional Programming Matters, 1989, Computer Journal, available online. • Alexandre Pereira Calsavara: Achieve better Java code with inner and anonymous classes, 2003, TechRepublic, available online. • Abhijit Belapurkar: Functional programming in the Java language, 2004, IBM developerWorks, available online.
  24. 24. Major use case for FOOP: Combinator libraries
  25. 25. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) The notion of combinator library Wikipedia as of 4 June 2013: “A combinator library is a software library which implements combinators for a functional programming language; "the key idea is this: a combinator library offers functions (the combinators) that combine functions together to make bigger functions". [...] These kinds of libraries are particularly useful for allowing domain-specific programming languages to be easily embedded into a general purpose language [...].“
  26. 26. Traversal combinators http://101companies.org/wiki/ Contribution:javaSyb
  27. 27. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Motivation of traversal combinators public static void cut(Company c) { Walker w = new Walker(c); for (Object o : w) if (o instanceof Employee) { Employee e = (Employee)o; e.setSalary(e.getSalary() / 2); } } http://101companies.org/wiki/Contribution:javaReflection How to be more typeful? What other traversals are conceivable?
  28. 28. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Motivation of traversal combinators public static Double total(Company c) { Walker w = new Walker(c); double result = 0; for (Object o : w) if (o instanceof Employee) { Employee e = (Employee)o; result += e.getSalary(); } return result; } http://101companies.org/wiki/Contribution:javaReflection How to be more typeful? What other traversals are conceivable?
  29. 29. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) The paradigm of using traversal combinators Identify problem-specific ingredients: Type-specific actions or functions. Represent these ingredients as closures. Extend those ingredients into generic ones. Apply a traversal scheme. Such schemes are closure combinators. Specifically,w e useSYB style.
  30. 30. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Problem-specific transformation functionality for “Cut” public static Action<Employee> updateSalary() { return new Action<Employee>() { public void apply(Employee x) { x.setSalary(x.getSalary() / 2); } }; } Update the salary when facing an employee along traversal http://101companies.org/wiki/Contribution:javaSyb
  31. 31. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Problem-specific query functionality for “Total” public static Function<Employee,Double> getSalary() { return new Function<Employee, Double>() { public Double apply(Employee x) { return x.getSalary(); } }; } Extract the salary when facing an employee along traversal http://101companies.org/wiki/Contribution:javaSyb
  32. 32. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Combine type-specific transformation with identity function public static <X> Action<Object> orIdentity(final Action<X> a) { return new Action<Object>() { public void apply(Object x) { try { a.apply((X)x); } catch (ClassCastException _) { } } }; } Rely on cast exception to check for applicability of type-specific case
  33. 33. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Combine type-specific query with constant function public static <X,Y> Function<Object,Y> orDefault( final Function<X,Y> f, final Y otherwise) { return or(f, new Function<Object,Y>() { public Y apply(Object x) { return otherwise; } }); } or uses cast in the same way as orIdentity.
  34. 34. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Apply traversal scheme for transformation public static void cut(Company c) { everywhere(orIdentity(updateSalary())).apply(c); } Try out every node
  35. 35. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Apply traversal scheme for query public static Double total(Company c) { return everything( orDefault(getSalary(), 0.0), add, 0.0).apply(c); } Try out every node Add intermediate results Start from “0.0”
  36. 36. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) The traversal scheme everywhere public static Action<Object> everywhere( final Action<Object> a) { return new Action<Object>() { public void apply(Object x) { all(everywhere(a)).apply(x); a.apply(x); } }; } Compose an action which applies argument action a to all the subobjects reachable from the object passed to the composed action.
  37. 37. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) The traversal scheme everywhere public static Action<Object> everywhere( final Action<Object> a) { return new Action<Object>() { public void apply(Object x) { all(everywhere(a)).apply(x); a.apply(x); } }; } Recurse into all immediate subobjects using reflection Apply the action to the last
  38. 38. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) The traversal scheme everything public static <Y> Function<Object,Y> everything( final Function<Object,Y> f, final BinaryOperator<Y> op, final Y initial) { return new Function<Object,Y>() { public Y apply(Object x) { return op.apply(f.apply(x), all( everything(f, op, initial), op, initial).apply(x)); } }; } Compose a function which applies argument function f to all the subobjects reachable while composing intermediate results with the binary operator op while starting from initial.
  39. 39. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) The traversal scheme everything public static <Y> Function<Object,Y> everything( final Function<Object,Y> f, final BinaryOperator<Y> op, final Y initial) { return new Function<Object,Y>() { public Y apply(Object x) { return op.apply(f.apply(x), all( everything(f, op, initial), op, initial).apply(x)); } }; }
  40. 40. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Traversal of companies DEMO http://101companies.org/wiki/ Contribution:javaSyb
  41. 41. Parser combinators http://101companies.org/wiki/ Contribution:javaParseLib
  42. 42. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) void department() { match(DEPARTMENT); match(STRING); match(OPEN); match(MANAGER); employee(); while (test(EMPLOYEE)) { match(EMPLOYEE); employee(); } while (test(DEPARTMENT)) department(); match(CLOSE); } department : 'department' STRING '{' ('manager' employee) ('employee' employee)* dept* '}'; Grammar production Corresponding procedure Motivation: how to avoid encoding of recursive descent parsing?
  43. 43. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) The paradigm of using parser combinators Model functor classes for acceptance & parsing. Model closure combinators for EBNF constructs. Sequence, Choice, Star, Plus, ... Model nonterminals as closure-returning methods. Encode RHS of productions in method body.
  44. 44. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) The types of acceptors and parsers public abstract class Acceptor { public abstract boolean accept(Input i); } public abstract class Parser<T> { public abstract T parse(Input i); } Abstract functor classes
  45. 45. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) An acceptor combinator for “*” public class Star extends Acceptor { private Acceptor a; public Star(Acceptor a) { this.a = a; } public boolean accept(Input i) { while (true) { int mark = i.getPos(); if (!a.accept(i)) { i.setPos(mark); return true; } } } } Accept input from i for as many times as possible. Make sure not to consume input that was seen when i was finally failing. (Backtracking needed.)
  46. 46. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) An acceptor combinator for “*” public class Star extends Acceptor { private Acceptor a; public Star(Acceptor a) { this.a = a; } public boolean accept(Input i) { while (true) { int mark = i.getPos(); if (!a.accept(i)) { i.setPos(mark); return true; } } } } Concrete functor class
  47. 47. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) public static Acceptor star(final Acceptor a) { return new Acceptor() { public boolean accept(Input i) { while (true) { int mark = i.getPos(); if (!a.accept(i)) { i.setPos(mark); return true; } } } }; } An alternative: a static function that returns a closure An acceptor combinator for “*”
  48. 48. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) public class Star<T> extends Parser<List<T>> { private Parser<T> p; public Star(Parser<T> p) { this.p = p; } public List<T> parse(Input i) { List<T> r = new LinkedList<T>(); while (true) { int mark = i.getPos(); T t = p.parse(i); if (t!=null) r.add(t); else { i.setPos(mark); return r; } } } } An parser combinator for “*” Given a parser p which returns a T, construct a parser which returns a list of Ts.
  49. 49. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) public class Star<T> extends Parser<List<T>> { private Parser<T> p; public Star(Parser<T> p) { this.p = p; } public List<T> parse(Input i) { List<T> r = new LinkedList<T>(); while (true) { int mark = i.getPos(); T t = p.parse(i); if (t!=null) r.add(t); else { i.setPos(mark); return r; } } } } Concrete functor class An parser combinator for “*”
  50. 50. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) EBNF of 101companies company : 'company' STRING '{' department* '}' EOF; department : 'department' STRING '{' ('manager' employee) ('employee' employee)* department* '}'; employee : STRING '{' 'address' STRING 'salary' FLOAT '}'; STRING : '"' (~'"')* '"'; FLOAT : ('0'..'9')+ ('.' ('0'..'9')+)?; Let’s parse companies again.
  51. 51. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Nonterminals as static fields public static final Acceptor STRING = WS(sequence( CHAR('"'), star(sequence(not(CHAR('"')),any)), CHAR('"'))); STRING : '"' (~'"')* '"';
  52. 52. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Nonterminals as methods public static Acceptor department() { return new Acceptor() { public boolean accept(Input i) { return ( sequence( SPECIAL("department"), STRING, SPECIAL("{"), employee("manager"), star(employee("employee")), star(department()), SPECIAL("}") )).accept(i); } }; } department : 'department' STRING '{' ('manager' employee) ('employee' employee)* department* '}'; What’s the limit of “nonterminals as static fields”?
  53. 53. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Parsing comapanies DEMO http://101companies.org/wiki/ Contribution:javaParseLib
  54. 54. (C) 2010-2013 Prof. Dr. Ralf Lämmel, Universität Koblenz-Landau (where applicable) Summary Functional OOP really combines OOP and FP: OOP: Encapsulation and generalization FP: Function application, composition, combination Major use case for FOOP: combinator libraries. There are languages more suitable for functional OOP: Java 8, F#, C#, Ruby, Python, ...

×