560 likes | 787 Views
YOUR LOGO HERE. Closures for Java. Neal Gafter Google. TS-2294. Why add Closures?. "In another thirty years people will laugh at anyone who tries to invent a language without closures, just as they'll laugh now at anyone who tries to invent a language without recursion." -Mark Jason Dominus.
E N D
YOUR LOGO HERE Closures for Java Neal Gafter Google TS-2294
Why add Closures? "In another thirty years people will laugh at anyone who tries to invent a language without closures, just as they'll laugh now at anyone who tries to invent a language without recursion." -Mark Jason Dominus
Outline Goals, Definitions Existing solutions Requirements Specification Examples New APIs
Outline Goals,Definitions Existing solutions Requirements Specification Examples New APIs
Goals • Concise “function” literals • without the pain of anonymous instances • Interoperate with existing APIs • Enable control APIs • Functional and Aggregate Operations • Simple but powerful
Definition: Closure A closure is a function that refers to free variables in its lexical context. A function is a block of code with parameters. It may produce a result value. A free variable is an identifier used but not defined by the closure.
Definition: Control API • API-specific statement forms • “special” methods, invocations • On par with built-in statements
Outline Goals, Definitions Existing solutions Requirements Specification Examples New APIs
Example: For-Each Using anonymous instances interface OneArg<A> { void invoke(A arg); } <T> void forEach(Collection<T> c, OneArg<T> block) { for (Iterator<T> it = c.iterator(); c.hasNext();) { block.invoke(it.next()); } }
Example: For-Each desired for (String s : strings) doThing(s); actual forEach(strings, new OneArg<String>() { public void invoke(String s) { doThing(s); } });
Example: For-Each desired String toString(Thing t) { … } for (Thing t : things) println(toString(t)); actual forEach(things, new OneArg<Thing>() { public void invoke(Thing t) { println(toString(t)); // error! } });
Example: For-Each desired for (String s : strings) if (…) throw new MyException(); actual forEach(strings, new OneArg<String>() { public void invoke(String s) { if (…) throw new MyException(); // error! } });
Example: For-Each desired for (String s : strings) if (…) return computeResult(s); actual forEach(strings, new OneArg<String>() { public void invoke(String s) { if (…) return computeResult(s); // error! } });
Example: For-Each desired String found = null; for (String s : strings) if (…) found = s; actual forEach(strings, new OneArg<String>() { public void invoke(String s) { if (…) found = s; // error! } });
Anonymous Instances • Verbose, extra wordy, clumsy, redundant • Closures are concise • Incomplete capture of lexical context • this, toString, etc. • return, break, continue • non-final local variables • Force irrelevant refactoring • Control APIs not possible • can’t wrap an arbitrary block of code
Outline Goals, Definitions Existing solutions Requirements Specification Examples New APIs
interface Candidate { Set<Qualification> qualifications(); } interface CandidatePool extends Collection<Candidate> { Object lock(); } Candidate recruit(CandidatePool candidates, Set<Qualification> requirements) { synchronized (candidates.lock()) { for (Candidate c : candidates) { if (c.qualifications() .containsAll(requirements)) { candidates.remove(c); return c; } } } return recruitForeign(requirements); } Program to be refactored
interface Candidate { Set<Qualification> qualifications(); } interface CandidatePool extends Collection<Candidate> { Lock lock(); } Candidate recruit(CandidatePool candidates, Set<Qualification> requirements) { withLock (candidates.lock()) { for (Candidate c : candidates) { if (c.qualifications() .containsAll(requirements)) { candidates.remove(c); return c; } } } return recruitForeign(requirements); } Program refactored
interface Candidate { Set<Qualification> qualifications(); } interface CandidatePool extends Collection<Candidate> { Lock lock(); } Candidate recruit(CandidatePool candidates, Set<Qualification> requirements) { withLock (candidates.lock()) { for (Candidate c : candidates) { if (c.qualifications() .containsAll(requirements)) { candidates.remove(c); return c; } } } return recruitForeign(requirements); } Program refactored
An app-specific example: time long t0 = System.nanoTime(); boolean success = false; try { doSomething(); success = true; } finally { recordTime(“doSomething”, success, System.nanoTime() – t0); }
An app-specific example: time time(“doSomething”) { doSomething(); }
Requirements for Closures • Simplify vs anonymous instances • Interoperate with existing APIs • Concise • Wrapped code not changed • Support Control APIs • API-specific control statements • On par with built-in statement forms
Outline Goals, Definitions Existing solutions Requirements Specification Examples New APIs
Closures Specification • Syntax and Semantics • closure expressions • function types • control statements • Transparency • local variables • exceptions • control transfers • completion (reachable)
Syntax: Closure Expressions {int x => x+1} {int x, int y => x+y} {String x => Integer.parseInt(x)} {=> System.out.println(“hello”);}
Syntax: Closure Expressions Primary:Closure Closure: { FormalParameterDeclsopt => BlockStatementsoptExpressionopt }
Semantics: Closure Expressions • Creates an object that represents • code of the body • lexical context • Few restrictions • May access locals, this • May return from enclosing method
Semantics: Closure Expressions • The closure conversion turns a closure into an instance of some interface • Provides interoperability with existing APIs. • You can restrict the closure’s operations • If no target type,use the natural function type
Syntax: Function Types {int => int} {int, int => int} {String => int throws NumberFormatException} { => void} {T => U}
Syntax: Function Types Type:{TypeListopt=> Type FunctionThrowsopt}
Semantics: Function Types {String => int throws NumberFormatException} is shorthand for java.lang.function.IO<String,NumberFormatException> where package java.lang.function; public interface IO<A, X extends Exception> { int invoke(A a0) throws X; }
Semantics: Function Types • “Ordinary” interface types • with an invoke method • You can extend, implement them • Declare variables, parameters, return types, etc. • Covariant results, etc. • (No special type rules)
Syntax: Control Statements withLock(lock, {=> doSomething(); });
Syntax: Control Statements withLock(lock) { doSomething(); }
Syntax: Control Statements ControlStatement:foroptPrimary(Formals : ExpressionListopt)StatementforoptPrimary(ExpressionListopt)Statement Is translated to Primary( ExpressionList, { Formals=>Statement });
Outline Goals, Definitions Existing solutions Requirements Specification Examples New APIs
Example: Control APIs Perform some operation while holding a java.util.concurrent.Lock (today) void incrementBalance(int deposit) { myLock.lock(); try { balance += deposit; } finally { myLock.unlock(); } }
Example: Control APIs Using a proposed new closure-based API void incrementBalance(int deposit) { Locks.withLock(myLock, { => balance += deposit; }); }
Example: Control APIs Using the control statement syntax void incrementBalance(int deposit) { Locks.withLock(myLock) { balance += deposit; } }
Example: Aggregate Operations Make a new list by applying a function to each element of an existing list List<Integer> parseInts(List<String> strings) throws NumberFormatException { return Collections.map( strings, {String s => Integer.decode(s)}); }
Example: Interaction w/ Existing APIs Launch a task using an Executor (today) void launch(Executor ex) { ex.execute(new Runnable() { public void run() { doSomething(); } }); }
Example: Interaction w/ Existing APIs Launch a task using an Executor (closure) void launch(Executor ex){ ex.execute({ => doSomething(); }); }
Example: Interaction w/ Existing APIs Or, using the control statement syntax void launch(Executor ex) { ex.execute() { doSomething(); } }
Example: Interaction w/ Existing APIs Add a swing listener (today) void addListener(final ItemSelectable is){ is.addItemListener( new ItemListener() { public void itemStateChanged(ItemEvent e) { doSomething(e, is); } } ); }
Example: Interaction w/ Existing APIs Add a swing listener (closure) void addListener(final ItemSelectable is){ is.addItemListener( { ItemEvent e => doSomething(e, is); } ); }
Example: Interaction w/ Existing APIs Or, using the control statement syntax void addListener(final ItemSelectable is){ is.addItemListener(ItemEvent e :) { doSomething(e, is); } }
Outline Goals, Definitions Existing solutions Requirements Specification Examples New APIs
New APIs • API-specific control constructs • Collections • Concurrency • Closables • Aggregate operations • Functional Primitives
Map-specific iteration Map<Key,Value> map = …; for eachEntry(Key k, Value v : map) { // operate with k, v here }
Locking Lock lock = …; withLock(lock) { // lock held here }