functional: Added functional lib
[nit.git] / lib / functional / README.md
1 # Nit functional types and Iterator API
2
3 This lib provides a common interfaces to represent and call any type of routine.
4 This is usefull if you want to build a functional API, where user can pass
5 functions. Right now, there's no support for anonymous function or function pointer.
6 However, one can build classes that inherit from a functional type to simulate
7 a function. Here's an example implementing the famous __map__ function:
8
9 ~~~
10 class MapIntToString
11         super Fun1[Int,String]
12         redef fun call(x) do return x.to_s
13 end
14
15 redef class Array[E]
16         fun map(mapper: Fun1[E, Object]): Array[Object]
17         do
18                 var res = new Array[Object]
19                 for ele in self do res.add(mapper.call(ele))
20                 return res
21         end
22 end
23
24 var xs = [1,2,3,4]
25 var f = new MapIntToString
26 assert xs.map(f) == ["1", "2", "3", "4"]
27 ~~~
28
29 Currently, this style of programming seems tedious, but future update of the langage
30 will support function pointer and anonymous function.
31
32 Functional API makes it easier to build asynchronous or multithreaded code,
33 because representing a pending or future computation using a function requires
34 much less code:
35
36 ~~~nitish
37 fun long\_calculation
38 do
39         ...
40 end
41
42 # function pointer
43 var thread = new Thread(&long\_calculation)
44 thread.start
45 thread.wait
46 ~~~
47
48 Finally, this lib provides an entire functional API over the `Iterator` class
49 similar to the old `Pipeline` lib.
50
51 ## Functional Types
52
53 There are two fundamental types: `FunX[0..X, RES]` and `ProcX[0..X]`, both inherits
54 `Routine`. The `X` represents the arity of the routine, eg :
55
56 ~~~
57 import functional
58
59 class A
60
61         # to_s isa `Fun0[String]`.
62         redef fun to_s do return "greeting from A"
63 end
64
65 # f isa `Fun2[Int,Int,Int]`
66 fun f(x: Int, y: Int): Int do return x + y
67
68 # g isa `Proc2[Int,Int]`
69 fun g(x: Int, y: Int) do print "{x + y}"
70 ~~~
71
72 For a `FunX` type the arity doesn't count the return type.
73
74 **Note**: The arity doesn't count the receiver of the current class where the
75 method belongs.
76
77 ## Iterator API
78
79 The new `Iterator` API provides all the classical functional style transformation:
80 map, for\_each, fold, fold1, flatmap, enumerate, any and all.
81
82 Most methods return a new `Iterator`, this allow us to chain them:
83
84 ~~~nitish
85 import functional
86
87 fun addone(x: Int): Int do return x + 1
88 fun square(x: Int): Int do return x * x
89 fun add(x:Int, y: Int): Int do return x + y
90
91 var xs = [1,2,3,4,5,6,7,8,9,10]
92
93 assert xs.iterator.map(&square).map(&addone).fold(0, &add) == 395
94 ~~~
95
96 Some functions collapse the iterator into one value : `all`, `any`, `fold`,
97 `fold1`, `for_each` (void-like).
98
99 **Note**: Most of the new methods tries to be lazy. However, `Iterator::order_by`
100 consume the entire iterator and `Iterator::filter` might consume the entire iterator.
101
102 ## Usage
103
104 To use the new API you must include in your file `import functional`.
105
106 ## Notes
107
108 - The module `functional::functional_gen` is only used to generate `functional::functional_types`.