In JavaScript currying and functional programming I looked at an Apps Script example using currying (embedding values that would normally be arguments in a function). Another functional programming topic that's becoming popular is the idea of composition. In React, Polymer and other similar frameworks, composable elements promote re-use. Composing functions has the same objective. Why not compose ?
What is composing ?It's a way of creating a function that applies a series of function an evolving result. You could think of it like this var result = f0(f1(f2(f3(f4(arg))))); A composed version of this would be compose (f0,f1,f2,f3,f4) (arg); or more likely var f = compose (f0,f1,f2,f3,f4) ; f (arg); The idea being that you could re-use each of the component functions in various combinations as required, including library functions, for example compose (myFunction , Math.sqrt , parseFloat ) ("3.9"); Would execute as var result = myFunction ( Math.sqrt ( parseFloat ("3.9"))); Why bother ?I wrote this article as a learning exercise for me, and I'm not entirely sure how I feel about the whole topic yet. In any case, let's plough on an see what develops ArgumentsA function can only return a single value, so that means that each function in the stack should only be expecting one argument, so objects may be required to pass through complex data from the innermost function. I guess there may be a way round this but I haven't figured it out. Be glad to have your ideas on the forum. General composerFirst off, I need a composer function. This looks pretty obscure, but I'm pretty happy with it, and I'll try to walk through it. function composer() { return Array.prototype.slice.call(arguments).reduceRight(function (prev, current) { return function () { return current(prev.apply(undefined, arguments)); }; }); }; It's expecting an argument list of functions which it will apply starting at the last one (this would be the innermost function), and will return a function that applies each of the functions in the list successively, so return Array.prototype.slice.call(arguments).reduceRight(function (prev, current) simply converts the arguments into a real array so I can use reduceRight (starting at the last argument) to execute each one in turn return function () { return current(prev.apply(undefined, arguments)); }; calls the current function - the arguments to it are the result of calling the previous function with the result so far. So the output of the composer function is another function that successively calls each of the functions that were passed to it. ExampleTo make this a slightly meatier example, I'm going to compose a function that consists of several pieces of Apps Script.
var sumColumn = composer ( // add all the values in column function (ob) { // miss the heading row return ob.values.slice(1).reduce (function (p,c) { return p+c[ob.package.column]; },0); }, // get the values function (ob) { return {values:ob.sheet.getDataRange().getValues(), package:ob.package}; }, // get the sheet function (ob) { return {sheet:ob.spreadsheet.getSheetByName (ob.package.sheetName), package:ob.package}; }, // get the spreadsheet function (package) { return {spreadsheet:SpreadsheetApp.openById(package.id), package:package}; } ); Notice that the functions are specified in the order outer to inner (with the inner executed first), and that I'm passing an object as the argument and the result so that these can be chained together and pass through the initial arguments. And now I can use it like this Logger.log ( sumColumn ({ id:'1181bwZspoKoP98o4KuzO0S11IsvE59qCwiw4la9kL4o', sheetName:"dupRemove", column:2}) ); And the result 41.0 Using this data Is it worth it?On the plus side I now have various functions that perform small tasks, which I could re-use, recompose with other things, amend etc. as well as a general purpose composer. On the other hand, for this task I could have just done Logger.log ( SpreadsheetApp.openById (id) .getSheetByName(sheetName) .getDataRange() .getValues() .slice (1) .reduce (function (p,c) { return c[column]+p; },0)); It has been interesting though and I'd be interested to hear how you'd use something like this For more like this, see Google Apps Scripts snippets. Why not join our community , follow the blog, twitter, G+ .You want to learn Google Apps Script?
|
Services > Desktop Liberation - the definitive resource for Google Apps Script and Microsoft Office automation > Google Apps Scripts snippets >