101101// reference
102102// http://www.jspatterns.com/
103103// http://shop.oreilly.com/product/9780596806767.do?sortby=publicationDate
104+
105+ // Here's a generic curry function (from kybernetikos):
106+ // It's slightly more complex than the common examples of currying (e.g. the one above), but that's because
107+ // the function can afterwards be called either in the normal way, or in the curried way.
108+ // If you call a 3 argument curried function with it, the returned function *is also curried*.
109+ // e.g. you can write func(arg1)(arg2)(arg3) or func(arg1, arg2, arg3) or func(arg1)(arg2, arg3) etc...
110+
111+ /* the curry procedure needs to know how many arguments are required before it should calculate the result */
112+ function curry ( func , minArgs ) {
113+ if ( minArgs == undefined ) { minArgs = 1 ; }
114+
115+ function funcWithArgsFrozen ( frozenargs ) {
116+ return function ( ) {
117+ // could do an optmisation here - if called with no arguments
118+ // return exactly this function.
119+ var args = Array . prototype . slice . call ( arguments ) ;
120+ var newArgs = frozenargs . concat ( args ) ;
121+ if ( newArgs . length >= minArgs ) {
122+ return func . apply ( this , newArgs ) ;
123+ } else {
124+ return funcWithArgsFrozen ( newArgs ) ;
125+ }
126+ } ;
127+ } ;
128+
129+ return funcWithArgsFrozen ( [ ] ) ;
130+ }
131+
132+ /* Here are some example uses - I use these with a functional immutable list structure implemented in js
133+ but they also work ok for normal higher order functions over arrays.
134+ */
135+
136+ var plus = curry ( function ( ) {
137+ var result = 0 ;
138+ for ( var i = 0 ; i < arguments . length ; ++ i ) {
139+ result += arguments [ i ] ;
140+ }
141+ return result ;
142+ } , 2 ) ;
143+
144+ /* Now you can call
145+ plus(3,2) // normal call
146+ plus(3) // partial application (returns a function that adds 3 to its argument)
147+ plus(3)(2) // complete application (returns 5)
148+ plus()(3)()()(2) // returns 5
149+ plus(3, 2, 4, 5) // the normal call can optionally take more than the minimum number of arguments
150+ plus(3)(2, 3, 5) // the last application can too.
151+ */
152+
153+ var minus = curry ( function ( x ) {
154+ var result = x ;
155+ for ( var i = 1 ; i < arguments . length ; ++ i ) {
156+ result -= arguments [ i ] ;
157+ }
158+ return result ;
159+ } , 2 ) ;
160+
161+ /* flip switches the order of the first two arguments on a function. It is curried itself and
162+ the function it returns is curried too. Particularly useful if you want a function that subtracts a number */
163+
164+ var flip = curry ( function ( func ) {
165+ return curry ( function ( a , b ) {
166+ return func ( b , a ) ;
167+ } , 2 ) ;
168+ } ) ;
169+
170+ /* for example
171+ minus(5) // returns a function that takes its argument away from 5
172+ flip(minus)(5) // returns a function that takes 5 away from its argument
173+ */
104174</ script >
105175</ body >
106176</ html >
0 commit comments