Flash Website Builder- Trendy Site Builder is a Flash Site Building tool that helps users build stunning websites. Check Out Custom Custom Logo Design by LogoBee. Website Design and Free Logo Templates available.
 CodingForums.com Heavy-duty curry function

Before you post, read our: Rules & Posting Guidelines

Enjoy an ad free experience by logging in. Not a member yet? Register.
 05-01-2008, 01:04 AM PM User | #1 Trinithis Regular Coder   Join Date: Jun 2007 Location: USA Posts: 527 Thanks: 26 Thanked 74 Times in 72 Posts Heavy-duty curry function This is a generalized curry function. It does normal currying plus a bit more. As you would expect, the curried function supports sequential partial application. However, This 'curry' function also allows for non-sequential partial application. It also allows the currying of variable argument functions. Curry function: Code: ```Function.freeArg = { toString: function() { return "[object FreeArg]"; } }; function curry(f /*, n [, a] */) { return f.curry(arguments[1], arguments[2]); } Function.prototype.curry = (function() { var toString = function() { return String(this.valueOf()); }; return function(/* n [, a] */) { var f = this; var a = arguments[1] || []; var n = typeof arguments[0] == "number" ? arguments[0] : f.length; return function() { if(!arguments.length) return arguments.callee; var p = a.slice(); var i = -1; while(i = p.indexOf(Function.freeArg, i + 1), i != -1) p[i] = p.shift.call(arguments); p.push.apply(p, arguments); if(n < 0) { var g = f.curry(n, p); g.valueOf = function() { return f.apply(null, p); }; g.toString = toString; return g; } if(p.length < n || p.indexOf(Function.freeArg) != -1) return f.curry(n, p); return f.apply(null, p); }; }; })(); if(!Array.prototype.indexOf) Array.prototype.indexOf = function(v, i) { var n = this.length; if((i |= 0) < 0) { i += n; if(i < 0) i = 0; } for(; i < n; ++i) if(this[i] === v) return i; return -1; };``` With non-sequential partial application, supply Function.freeArg in the argument to be temporarily bypassed. In my example, I declare _ to equal Function.freeArg to give the code a more functional feel. With variable arg currying (mandatory if you repeatedly do partial application, but otherwise not), when you curry the function, you need to specify the number of arguments to curry as a negative number, such as -1. Normally the curry function infers the number of arguments to curry as the default function argument length. In the case that you do supply the negative value length argument, any application of the returned function always return a function that always returns a function, etc. To get the value of the function, you need to force its value either explicitly or implicitly via the toString or valueOf methods of the function. Example code: Code: ```var _ = Function.freeArg; ------------------------------------- // a curried add function var add = curry(function(x, y) { return x + y; }); var inc = add(1); ------------------------------------- // a curried sub function var sub = curry(function(x, y) { return x - y; }); var oneMinus = sub(1); var dec = sub(_, 1); ------------------------------------- // a variable argument average function var average = curry(function() { var sum = 0; for(var i = 0; i < arguments.length; ++i) { sum += arguments[i]; } return sum / arguments.length; }, -1); // note the -1 argument! var avg_4_7_args = average(4, 7); var avg_4_7_0_args = avg_4_7_args(0); var avg_1_2_3_args = average(1)(2)(3); ------------------------------------- var alert_x_y_z_w = function(x, y, z, w) { alert([x, y, z, w].join('\n')); }.curry(); // OO-style var alert_1_y_2_w = alert_x_y_z_w(1, _, 2, _); ------------------------------------- var x = 5; alert(inc(x)); alert(oneMinus(x)); alert(dec(x)); alert(avg_4_7_args(1, 2, 3)); alert(avg_4_7_0_args(1,2)(3)(4,5,6)); alert(avg_1_2_3_args()); alert_1_y_2_w(3, 4);``` The example code doesn't show much or explain much, but what it does demonstrate is the flexibility of how you can call the curried function. To understand what currying is, you can try: - http://ianhenderson.org/currying_in_javascript.html - http://www.google.com/search?hl=en&q...=Google+Search In the short, a curried function allows you to pass one argument at a time to a function, and that will return a new function if there are arguments that you "still need to pass" into the function. __________________ Trinithis Last edited by Trinithis; 05-02-2008 at 04:51 AM..
 05-04-2008, 05:06 AM PM User | #2 fside Regular Coder   Join Date: Mar 2008 Posts: 301 Thanks: 2 Thanked 30 Times in 30 Posts I've seen this on the web, and wondered if it doesn't provide another example of how to use this thing. I wonder, though, is this really what Curry had in mind. As I read your links, 'currying' removes an argument, first or last, so using n-1 arguments. But this 'curry', if that's what it is, is useful because it gets the machine to do what one otherwise might have to do with multiple handlers or multi-dim objects. Here, you just send function for any object, and it works in its own 'space', almost like a 'class'. It doesn't know about other objects though to test for collision. Maybe it could? The 'moveit' function is just an example, it could be any function at all obviously. Here, since the onclick is set, initially, onclick is fired again within moveit to keep the animation going. Code: ```

Run Jack Run
```

 05-04-2008, 06:16 AM PM User | #3 Trinithis Regular Coder   Join Date: Jun 2007 Location: USA Posts: 527 Thanks: 26 Thanked 74 Times in 72 Posts What you have posted is not a curry function. It's actually partial application function. While they are closely related, they are not the same thing. Partial application is simpler to understand. Partial application is where you supply some of the arguments to a function but not all of them. Then you get a new function that remembers those and asks for the remaining functions before execution. In a sense, curring is a technique to enable automatic partial application. More formally, currying is a technique to turn a function into a function that accepts one and only one argument. In turn, when called, that function returns another function that accepts one and only one argument . . . and so on until the 'original' function is able to be executed. Take for example, real number subtraction (call it f) in a math sense. f requires two inputs, both of which are real number. Then it returns another real number. Note: R x R (same as R^2) is simply a pair of real numbers (x, y). We say that f is a function from two real number to a real number. That is in math notation . . . Code: `f : R x R -> R` or more compactly . . . Code: `f : R^2 -> R` So what this is saying is that f takes two real numbers for input and returns a real number. In C++, this notation looks like: Code: `real f(real, real)` In Haskell, this notation looks like: Code: `f :: (Real, Real) -> Real` Well, when you curry f, call it f', you get: Code: `f' : R -> (R -> R)` In C++, this might look something like: Code: `realToReal f_prime(real)` In Haskell Code: `f' :: Real -> (Real -> Real)` In all, curring a function creates a new function which allows you to feed an argument into it one at a time rather than all at once. Hope this helps, though I'm not sure if I'm being too mathy. Edit: You might want to look at closures: http://en.wikipedia.org/wiki/Closure_(computer_science) http://www.dynamicdrive.com/forums/s...80&postcount=6 http://www.codingforums.com/showthread.php?t=129742 __________________ Trinithis Last edited by Trinithis; 05-04-2008 at 06:26 AM..
 05-04-2008, 08:11 AM PM User | #4 fside Regular Coder   Join Date: Mar 2008 Posts: 301 Thanks: 2 Thanked 30 Times in 30 Posts I appreciate the clarification. I've been reading a number of pages now on this, and I see the difference. Frankly, I'd never heard of either until your thread. Lot to learn.
 05-04-2008, 08:22 AM PM User | #5 Trinithis Regular Coder   Join Date: Jun 2007 Location: USA Posts: 527 Thanks: 26 Thanked 74 Times in 72 Posts Oh, I just looked at your moveit code. Just so you know, you are doing too much with your "curry" (should have been named "partialApply") function. While what you did does work, the scope variable is intended to be used only when applied on a method with a specific object is in mind. If you have seen a Function.prototype.bind function, it is similar to that. What you have: Code: `ary[i].onclick = curry(ary[i], function(e) { moveit(this, e) });` What you should have done: Code: `ary[i].onclick = curry(null, moveit, ary[i]);` If you used a real curry function, such as mine, you could have written the code as one of the following: Code: ```ary[i].onclick = curry(moveit)(ary[i]); ary[i].onclick = moveit.curry()(ary[i]); // with mine you can save a little computation by doing it like: ary[i].onclick = curry(moveit, null, [ary[i]]); ary[i].onclick = moveit.curry(null, [ary[i]]);``` I googled a site for Function.prototype.bind, and I found: http://www.brockman.se/writing/metho...nces.html.utf8 It has a definition, and it looks promising in other functional programming aspects. __________________ Trinithis Last edited by Trinithis; 05-04-2008 at 08:31 AM.. Reason: grammar
 05-15-2008, 05:18 AM PM User | #6 RexxCrow Regular Coder     Join Date: Jul 2006 Location: California Posts: 275 Thanks: 6 Thanked 2 Times in 2 Posts What exactly is a "curry function", curry means to beat, bash, and thrash, to tan leather, to clean the coat of a horse, I am not seeking what that has exactly to do with a function? __________________
 05-15-2008, 06:24 AM PM User | #7 jkd Senior Coder     Join Date: May 2002 Location: metro DC Posts: 3,163 Thanks: 1 Thanked 18 Times in 18 Posts This is a currying decorator I wrote a while ago: http://www.browserland.org/scripts/curry/ It relies on the function.length property to determine the number of arguments to expect, although that can be overrode manually. __________________ jasonkarldavis.com
 05-19-2008, 06:56 AM PM User | #8 Trinithis Regular Coder   Join Date: Jun 2007 Location: USA Posts: 527 Thanks: 26 Thanked 74 Times in 72 Posts @RexxCrow It's named after Haskell Curry __________________ Trinithis
05-23-2008, 07:14 AM   PM User | #9
fside
Regular Coder

Join Date: Mar 2008
Posts: 301
Thanks: 2
Thanked 30 Times in 30 Posts
Quote:
 Originally Posted by RexxCrow What exactly is a "curry function"
There were links explaining it, above, and my own reference to a man's name.

I liked the closure it provides, especially that PAF as it was pointed out, so that 'the computer' handles each object, previous states, present states, etc. 'Set and forget'. No need for extra arrays or objects to track that for separate instances. It's done 'automatically'.

 Bookmarks

 Thread Tools Rate This Thread Rate This Thread: 5 : Excellent 4 : Good 3 : Average 2 : Bad 1 : Terrible

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is Off HTML code is Off Forum Rules
 Forum Jump User Control Panel Private Messages Subscriptions Who's Online Search Forums Forums Home :: Client side development     JavaScript programming         DOM and JSON scripting         Ajax and Design         JavaScript frameworks         Post a JavaScript     HTML & CSS     XML     Flash & ActionScript         Adobe Flex     Graphics and Multimedia discussions     General web building         Site reviews         Building for mobile devices :: Server side development     Apache configuration     Perl/ CGI     PHP         Post a PHP snippet     MySQL         Other Databases     Ruby & Ruby On Rails     ASP     ASP.NET     Java and JSP     Other server side languages/ issues         ColdFusion         Python :: Computing & Sciences     Computer Programming     Computer/PC discussions     Geek News and Humour Web Projects and Services Marketplace     Web Projects         Small projects (quick fixes and changes)         Medium projects (new script, new features, etc)         Large Projects (new web application, complex features etc)         Unknown sized projects (request quote)         Vacant job positions         Looking for work/ for hire         Project collaboration/ partnership         Paid work offers and requests (Now CLOSED)     Career, job, and business ideas or advice     Domains, Sites, and Designs for sale         Domains for sale         Websites for sale         Design templates and graphics for sale :: Other forums     Member Offers     Forum feedback and announcements

All times are GMT +1. The time now is 11:58 AM.