04/23/07 linq- Why do you want to know about functional programming? A look at LinQ in C# and (perhaps) Java Axel T. Schreiner RIT — Computer Science Eric Meijer 1 http://www.cs.rit.edu/~ats/talks/linq-ieee/ http://www.cs.rit.edu/~ats/cs-2006-1/14_linq.pdf
51
Embed
Why do you want to know about functional programming?ats/talks/linq-ieee/linq-ieee.pdf · 04/23/07 linq-Why do you want to know about functional programming? A look at LinQ in C#
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
04/23/07 linq-
Why do you want to know about functional programming?
Implement the necessary methods for IEnumerable, XML- and database-access.
Sugar syntax liberally.
3
cs-2006-1 10/30/06 linq-
What if...
Syntactic sugar patterned after SQL.
4
struct Person { string first, last; int phone; }IContainer<Person> staff = ...Console.WriteLine( from x in staff where x.phone % 2 == 0 orderby x.last select new { x.first, x.phone });
cs-2006-1 10/30/06 linq-
What if...
Syntactic sugar patterned after SQL.
Actions converted into messages,Expressions converted into functions.
5
struct Person { string first, last; int phone; }IContainer<Person> staff = ...Console.WriteLine( from x in staff where x.phone % 2 == 0 orderby x.last select new { x.first, x.phone });
cs-2006-1 10/30/06 linq-
What if...
Functional style [Eric Meijer]:
function as arguments,function composition for actions.
Anonymous class new { field ,... }.6
struct Person { string first, last; int phone; }IContainer<Person> staff = ...Console.WriteLine( staff .Where(x => x.phone % 2 == 0) .OrderBy(x => x.last) .Select(x => new { x.first, x.phone }));
➦
cs-2006-1 10/30/06 linq-
Typing
7
struct Person { string first, last; int phone; }IContainer<Person> staff = ...Console.WriteLine( staff .Where(x => x.phone % 2 == 0) .OrderBy(x => x.last) .Select(x => new { x.first, x.phone }));
class C<T> { delegate R Func<R, T> (T arg); C<T> Where (Func<bool, T> predicate); C<T> OrderBy<K> (Func<K, T> keySelector); C<U> Select<U> (Func<U, T> selector);}
cs-2006-1 10/30/06 linq-
Typing
8
class C<T> { delegate R Func<R, T> (T arg); C<T> Where (Func<bool, T> predicate); C<T> OrderBy<K> (Func<K, T> keySelector); C<U> Select<U> (Func<U, T> selector);}
struct Person { string first, last; int phone; }IContainer<Person> staff = ...Console.WriteLine( staff .Where(x => x.phone % 2 == 0) .OrderBy(x => x.last) .Select(x => new { x.first, x.phone }));
cs-2006-1 10/30/06 linq-
Typing
9
class C<T> { delegate R Func<R, T> (T arg); C<T> Where (Func<bool, T> predicate); C<T> OrderBy<K> (Func<K, T> keySelector); C<U> Select<U> (Func<U, T> selector);}
struct Person { string first, last; int phone; }IContainer<Person> staff = ...Console.WriteLine( staff .Where(x => x.phone % 2 == 0) .OrderBy(x => x.last) .Select(x => new { x.first, x.phone }));
cs-2006-1 10/30/06 linq-
Typing Pattern
10
class C<T> { delegate R Func<R, T> (T arg); C<T> Where (Func<bool, T> predicate); C<T> OrderBy<K> (Func<K, T> keySelector); C<U> Select<U> (Func<U, T> selector);}
struct Person { string first, last; int phone; }IContainer<Person> staff = ...Console.WriteLine( staff .Where(x => x.phone % 2 == 0) .OrderBy(x => x.last) .Select(x => new { x.first, x.phone }));
IEnumerable<T> Where<T> (IEnumerable<T> container, Func<bool,T> predicate) { foreach (var c in container) if (predicate(c)) yield return c;}
Implementation
15
04/23/07 linq-
public interface Func<R,A> { R f (A a); }public<T> Iterable<T> where (Iterable<T> container, Func<Boolean,T> predicate) { List<T> result = newList(); for (T c: container) if (predicate.f(c)) result.add(c); return result;}
delegate R Func<R,A> (A a);
IEnumerable<T> Where<T> (IEnumerable<T> container, Func<bool,T> predicate) { foreach (var c in container) if (predicate(c)) yield return c;}
Implementation
15
04/23/07 linq-
Lazy Evaluation
16
public<T> IterableImpl<T> where (final Func<Boolean,T> predicate) { return new IterableImpl<T>(this) { public Iterator<T> iterator () { return new IteratorImpl<T> () { final Iterator<T> c = delegate.iterator(); protected void getNext () { while (c.hasNext()) if (predicate.f(next = c.next())) { hasNext = true; return; } hasNext = false; eof = true;} };} };}
04/23/07 linq-
int[] xs = { 1, 2, 3, 4, 5 };
from x in xs where x % 2 == 0 select x
Where(xs, x => x % 2 == 0)
Use
17
04/23/07 linq-
List<Integer> xs = Arrays.asList(new Integer[]{ 1, 2, 3, 4, 5});where(xs, new Func<Boolean,Integer>() { public Boolean f (Integer x) { return x % 2 == 0; }})
int[] xs = { 1, 2, 3, 4, 5 };
from x in xs where x % 2 == 0 select x
Where(xs, x => x % 2 == 0)
Arrays are not Iterable.
Use
17
cs-2006-1 10/30/06 linq-
Sugar: Extension Methods
A static class can define (static) extension methods.
If the class is imported, the methods can be called as instance methods:
18
static class X { static R method (this A parm, ...) { ... }}
A a;a.method(...)
cs-2006-1 10/30/06 linq-
Sugar: Lambda Syntax
An anonymous method definition can be significantly simplified.
Parameter and result types can be inferred.
Proposed for Java 7.
19
parameter => expression(type parameter, ...) => { body }
cs-2006-1 10/30/06 linq-
select / Select
20
from x in xs select f
xs.Select(x => f)
creates new records.
04/23/07 linq-
delegate R Func<R,A> (A a);
IEnumerable<U> Select<U,T> (IEnumerable<T> container, Func<U,T> selector) { foreach (var c in container) yield return selector(c);}
Implementation
21
04/23/07 linq-
public interface Func<R,A> { R f (A a); }public<U,T> Iterable<U> select (Iterable<T> container, Func<U,T> selector) { List<U> result = newList(); for (T c: container) result.add(selector.f(c)); return result;
}
delegate R Func<R,A> (A a);
IEnumerable<U> Select<U,T> (IEnumerable<T> container, Func<U,T> selector) { foreach (var c in container) yield return selector(c);}
Implementation
21
04/23/07 linq-
Lazy Evaluation
22
public<U,T> IterableImpl<U> select (final Func<U,T> selector) { return new IterableImpl<U>(this) { public Iterator<U> iterator () { return new IteratorImpl<U> () { final Iterator<T> c = delegate.iterator(); protected void getNext () { if (hasNext = c.hasNext()) next = selector.f(c.next()); else eof = true;} };} };}
cs-2006-1 10/30/06 linq-
select / Select[Many]
23
from x in xs select f
xs.Select(x => f)
creates new records.
from x in xs from y in ys select f
xs.SelectMany(x => ys.Select(y => f))
creates new records — notice scoping.
04/23/07 linq-
delegate R Func<R,A> (A a);
IEnumerable<U> SelectMany<U,T> (IEnumerable<T> container, Func<IEnumerable<U>,T> selector) { foreach (var c in container) foreach (var u in selector(c)) yield return u;}
Implementation➦
24
04/23/07 linq-
public interface Func<R,A> { R f (A a); }public<U,T> Iterable<U> selectMany (Iterable<T> container, Func<Iterable<U>,T> selector) { List<U> result = newList(); for (T c: container) for (U u: selector.f(c)) result.add(u); return result;
}
delegate R Func<R,A> (A a);
IEnumerable<U> SelectMany<U,T> (IEnumerable<T> container, Func<IEnumerable<U>,T> selector) { foreach (var c in container) foreach (var u in selector(c)) yield return u;}
selectMany( where(xs, new Func<Boolean,Integer>() { public Boolean f (Integer x) { return x > 3; } }), new Func<Iterable<HashMap<String,Object>>,Integer>() { public Iterable<HashMap<String,Object>> f (final Integer x) { return select( where(ys, new Func<Boolean,Double>() { public Boolean f (Double y) { return y < 8.0; } }), new Func<HashMap<String,Object>,Double>() { public HashMap<String,Object> f (Double y) { HashMap<String,Object> result = new HashMap<String,Object>(); result.put("y", y); result.put("x", x); return result; } }); } })
cs-2006-1 10/30/06 linq-
orderby
29
e.OrderBy(x => f) // .ThenBy(x => g) ...
from x in e orderby f [ascending|descending] // , g ,...
defines sort key[s] and direction.
04/23/07 linq-
public<K extends Comparable<K>,T> Ordered<T> orderBy (Iterable<T> container, final Func<K,T> key) { // need a copied list for sorting List<T> values = newList(); for (T c: container) values.add(c);
return new Ordered<T>(values, new Comparator<T>() { public int compare (T a, T b) { return key.f(a).compareTo(key.f(b)); } } );}
Implementation:primary key
Comparator is composed from key
30
04/23/07 linq-31
public static class Ordered<T> extends Base<T> { protected final Comparator<T> order; protected boolean ordered; // true once sorted
public<K extends Comparable<K>> Ordered<T> thenBy (final Func<K,T> key) { // add to order return new Ordered<T>(super.getValues(), new Comparator<T>() { public int compare (T a, T b) { int c = order.compare(a, b); return c != 0 ? c : key.f(a).compareTo(key.f(b)); } } );}
next Comparator is composed from order and key
Implementation:secondary keys
04/23/07 linq-32
protected static class Base<T> extends AbstractList<T> { private final List<T> values; protected List<T> getValues () { return values; }
public Base (List<T> values) { this.values = values; }
public void add (int index, T element) { getValues().add(index, element); } // ...
protected List<T> getValues () { // use order List<T> values = super.getValues(); if (!ordered) { Collections.sort(values, order); ordered = true; } return values; }
Implementation:sort
get, remove, set, and size are also delegated; any use of values can be overridden:
04/23/07 linq-
Use
sorts in dictionary order
33
public static void main (String... _args) { List<String> args = Arrays.asList(_args); orderBy(args, new Func<String,String>() { // s => s.toLowerCase public String f (String s) { return s.toLowerCase(); }}) .thenBy(new Func<String,String>() { // s => s public String f (String s) { return s; } })
04/23/07 linq-
joincomputes for pairs: inner record with same key as outer record
group-joincomputes for group of inner records with same key as outer record
group bygroups values computed from elements with equal key values
34
etc.➦
cs-2006-1 10/30/06 linq-
from join...
35
from x in e join y in f on g equals h into i // ... z
e.GroupJoin(f, x => g, y => h, (x,i) => z)
defines anonymous iteration over groups.
from x in e join y in f on g equals h // ... z
e.Join(f, x => g, y => h, (x,y) => z)
defines anonymous iteration over pairs.
from x in e
defines iteration variable.
cs-2006-1 10/30/06 linq-
Join
36
delegate R F<R,A> (A a);delegate R F<R,A,B> (A a, B b);
C<V> Join<U,K,V,T> (C<U> inner, F<K,T> outerKey, F<K,U> innerKey, F<V,T,U> selector) { var result = new C<V>(); foreach (var t in this) // from's container foreach (var i in inner) if (outerKey(t).Equals(innerKey(i))) result.Add(selector(t, i)); return result;}
selector combines records with matching keys.
cs-2006-1 10/30/06 linq-
GroupJoin
37
C<V> GroupJoin<U,K,V,T> (C<U> inner, F<K,T> outerKey, F<K,U> innerKey, F<V,T,C<U>> selector) { var result = new C<V>(); foreach (var t in this) { var group = new C<U>(); foreach (var i in inner) if (outerKey(t).Equals(innerKey(i))) group.Add(i); result.Add(selector(t, group)); } return result;}
selector combines outer record with group of inner records and matching keys.
C<Group<K,E>> GroupBy<K,E,T> (F<K,T> key, F<E,T> selector) { var dictionary = new Dictionary<K,Group<K,E>>(); var result = new C<Group<K,E>>(); foreach (var t in this) { var k = key(t); Group<K,E> group; try { group = dictionary[k]; } catch { group = new Group<K,E>(k); result.Add(group); dictionary[k] = group; } group.Add(selector(t)); } return result; }}
cs-2006-1 10/30/06 linq-
Group
40
class Group<K,T> : C<T> { readonly K key;
public Group (K key) { this.key = key; }
public K Key { get { return key; } }}
Group preserves the common key value.
04/23/07 linq-
Think functional!
A computer scientist invents this...
Action sequence: compositionCondition/selection: lambdas as argumentsNested selections: application of lambda Sorting: compose Comparator based on lambda arguments
No chance to see this in Java [56]...
41
04/23/07 linq-
Think functional!
A computer scientist invents this...
Action sequence: composition, lazy evaluationCondition/selection: lambdas as argumentsNested selections: application of lambda Sorting: compose Comparator based on lambda arguments
No chance to see this in Java [56]...
42
04/23/07 linq-
Think functional!
A computer scientist invents this...
Action sequence: composition, lazy evaluationCondition/selection: lambdas as argumentsNested selections: application of lambda Sorting: compose Comparator based on lambda arguments
No chance to see this in Java [56]...
43
04/23/07 linq-
Think functional!
A computer scientist invents this...
Action sequence: composition, lazy evaluationCondition/selection: lambdas as argumentsNested selections: application of lambda Sorting: compose Comparator based on lambda arguments
No chance to see this in Java [56]...
44
04/23/07 linq-
Think functional!
A computer scientist invents this...
Action sequence: composition, lazy evaluationCondition/selection: lambdas as argumentsNested selections: application of lambda Sorting: compose Comparator based on lambda arguments
No chance to see this in Java [56]...
45
04/23/07 linq-
Think functional!
A computer scientist invents this...
Action sequence: compositionCondition/selection: lambdas as argumentsNested selections: application of lambda Sorting: compose Comparator based on lambda arguments
No chance to see this in Java [56]...
46
04/23/07 linq-
References
Erik Meijerhttp://research.microsoft.com/~emeijer/