why do you want to know about functional programming?ats/talks/linq-ieee/linq-ieee.pdf · 04/23/07...

Post on 06-Jul-2020

6 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

04/23/07 linq-

Why do you want to know about functional programming?

A look at LinQ in C# and (perhaps) Java

Axel T. SchreinerRIT — 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

04/23/07 linq-

Principles

Patterns

Examples

Implementation

Conclusions

2

cs-2006-1 10/30/06 linq-

Principles

Map a query language to cascading method calls.

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 }));

cs-2006-1 10/30/06 linq-

Query Expression Pattern

11

from join... introduce iteration variable(s)

fromlet ...where

introduces iteration variable(s)introduces variablefilters

orderby rearranges sequence

selectgroup by

produces flat resultproduces structured result

into join...

produces iteration variable(s) to start over

cs-2006-1 10/30/06 linq-

Query Class Pattern

12

from join...

class C<T> { C<V> Join (...) C<V> GroupJoin (...)

fromlet ...where

C<T> Where (...)

orderby

O<T> OrderBy[Descending] (...) class O<T> : C<T> { O<T>ThenBy[Descending] (...) }

selectgroup by

C<U> Select[Many] (...) C<G<Key,E>> GroupBy (...) class G<Key,E> : C<E> {...}

into join...

04/23/07 linq-

Exampleshttp://www.cs.rit.edu/~ats/cs-2006-1/code/adt/query/

http://www.cs.rit.edu/~ats/talks/linq-ieee/linq/

13

cs-2006-1 10/30/06 linq-

from let where ... / Where

14

from x in xs where f

xs.Where(x => f)

retains only records satisfying a condition.

let x = e

defines name for value.

04/23/07 linq-

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-

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;}

Implementation➦

24

04/23/07 linq-

int[] xs = { 1, 2, 3, 4, 5 };double[] ys = { 6.0, 7.0, 8.0, 9.0, 10.0 };

from x in xs where x > 3 from y in ys where y < 8.0 select new { y, x }

SelectMany(Where(xs, x => x > 3), x => Select(Where(ys, y => y < 8.0), y => new { y, x }))

Use

25

cs-2006-1 10/30/06 linq-

Sugar: Tuple Types

A type can be created on the fly.

It has a read/write property for each field (and ToString).

The field types (and names) are inferred.

26

new { name = expression, ... }

04/23/07 linq-

int[] xs = { 1, 2, 3, 4, 5 };double[] ys = { 6.0, 7.0, 8.0, 9.0, 10.0 };

from x in xs where x > 3 from y in ys where y < 8.0 select new { y, x }

SelectMany(Where(xs, x => x > 3), x => Select(Where(ys, y => y < 8.0), y => new { y, x }))

Review: Use

27

04/23/07 linq-28

List<Integer> xs = Arrays.asList(new Integer[]{ 1, 2, 3, 4, 5});final List<Double> ys = Arrays.asList(new Double[]{ 6.0, 7.0, 8.0, 9.0, 10.0 });

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 Ordered (List<T> values, Comparator<T> order) { super(values); this.order = order; }

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.

cs-2006-1 10/30/06 linq-

group by

38

from x in e group x by g

e.GroupBy(x => g)

groups elements by key value.

from x in e group f by g

e.GroupBy(x => g, x => f)

groups new values by key value.

cs-2006-1 10/30/06 linq-

GroupBy

39

C<Group<K,T>> GroupBy<K,T> (F<K,T> key) { return GroupBy(key, (F<T,T>)delegate (T t) { return t; });}

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/

C#: LinQhttp://msdn.microsoft.com/netframework/future/linq/

C# 3.0http://msdn2.microsoft.com/en-us/vcsharp/aa336745.aspx

Java 7: Closureshttp://www.javac.info/closures-v03.html

47

top related