X-Git-Url: http://nitlanguage.org diff --git a/lib/functional/README.md b/lib/functional/README.md new file mode 100644 index 0000000..849a1ae --- /dev/null +++ b/lib/functional/README.md @@ -0,0 +1,108 @@ +# Nit functional types and Iterator API + +This lib provides a common interfaces to represent and call any type of routine. +This is usefull if you want to build a functional API, where user can pass +functions. Right now, there's no support for anonymous function or function pointer. +However, one can build classes that inherit from a functional type to simulate +a function. Here's an example implementing the famous __map__ function: + +~~~ +class MapIntToString + super Fun1[Int,String] + redef fun call(x) do return x.to_s +end + +redef class Array[E] + fun map(mapper: Fun1[E, Object]): Array[Object] + do + var res = new Array[Object] + for ele in self do res.add(mapper.call(ele)) + return res + end +end + +var xs = [1,2,3,4] +var f = new MapIntToString +assert xs.map(f) == ["1", "2", "3", "4"] +~~~ + +Currently, this style of programming seems tedious, but future update of the langage +will support function pointer and anonymous function. + +Functional API makes it easier to build asynchronous or multithreaded code, +because representing a pending or future computation using a function requires +much less code: + +~~~nitish +fun long\_calculation +do + ... +end + +# function pointer +var thread = new Thread(&long\_calculation) +thread.start +thread.wait +~~~ + +Finally, this lib provides an entire functional API over the `Iterator` class +similar to the old `Pipeline` lib. + +## Functional Types + +There are two fundamental types: `FunX[0..X, RES]` and `ProcX[0..X]`, both inherits +`Routine`. The `X` represents the arity of the routine, eg : + +~~~ +import functional + +class A + + # to_s isa `Fun0[String]`. + redef fun to_s do return "greeting from A" +end + +# f isa `Fun2[Int,Int,Int]` +fun f(x: Int, y: Int): Int do return x + y + +# g isa `Proc2[Int,Int]` +fun g(x: Int, y: Int) do print "{x + y}" +~~~ + +For a `FunX` type the arity doesn't count the return type. + +**Note**: The arity doesn't count the receiver of the current class where the +method belongs. + +## Iterator API + +The new `Iterator` API provides all the classical functional style transformation: +map, for\_each, fold, fold1, flatmap, enumerate, any and all. + +Most methods return a new `Iterator`, this allow us to chain them: + +~~~nitish +import functional + +fun addone(x: Int): Int do return x + 1 +fun square(x: Int): Int do return x * x +fun add(x:Int, y: Int): Int do return x + y + +var xs = [1,2,3,4,5,6,7,8,9,10] + +assert xs.iterator.map(&square).map(&addone).fold(0, &add) == 395 +~~~ + +Some functions collapse the iterator into one value : `all`, `any`, `fold`, +`fold1`, `for_each` (void-like). + +**Note**: Most of the new methods tries to be lazy. However, `Iterator::order_by` +consume the entire iterator and `Iterator::filter` might consume the entire iterator. + +## Usage + +To use the new API you must include in your file `import functional`. + +## Notes + +- The module `functional::functional_gen` is only used to generate `functional::functional_types`.