In the midst of discussing my runnables technique for implementing function pointers over on the Rausch Generator Blog, I commented about the usefulness of the currying technique, mostly in callbacks. It occurred to me that I’ve been using a tiny helper class to curry functions for years in both AS2 and AS3, but that many people may have never stopped to write such a basic (in my opinion) class. So I figured I might as well re-implement the class and post it here.

The idea behind the class is that oftentimes you would like to pass along some data you have to a function in addition to what the function would normally be passed. For example, an event listener function takes only one argument: the Event. If you have some data handy as a local variable, you normally would need to store this as a field and retrieve it later. This is clumsy and results in lots of extra code which bloats your SWF size. Currying can greatly help you here! Consider some pseudo-code for a sprite that displays a student portrait and name as a single bitmap without using currying:

class StudentViewer extends Sprite
{
	private var __student:XML;
 
	function StudentViewer(url:String): void
	{
		loadXML(url, onStudentLoaded);
	}
	function onStudentLoaded(student:XML): void
	{
		__student = student;
		loadImage(student.portrait, onPortraitLoaded);
	}
	function onPortraitLoaded(portrait:DisplayObject): void
	{
		var tf:TextField = new TextField();
		tf.width = portrait.width;
		tf.text = __student.first + " " + __student.last;
 
		var bmd:BitmapData = new BitmapData(portrait.width, portrait.height);
		bmd.draw(portrait);
		bmd.draw(tf);
		addChild(new Bitmap(bmd));
 
		__student = null;
	}
}

The downside here is that the student XML needs to be manually stored in a field and cleaned up later to free the memory. Let’s see how currying helps this situation:

class StudentViewer extends Sprite
{
	function StudentViewer(url:String): void
	{
		loadXML(url, onStudentLoaded);
	}
	function onStudentLoaded(student:XML): void
	{
		loadImage(student.portrait, CurryFunction.create(this, onPortraitLoaded, student));
	}
	function onPortraitLoaded(portrait:DisplayObject, student:XML): void
	{
		var tf:TextField = new TextField();
		tf.width = portrait.width;
		tf.text = student.first + " " + student.last;
 
		var bmd:BitmapData = new BitmapData(portrait.width, portrait.height);
		bmd.draw(portrait);
		bmd.draw(tf);
		addChild(new Bitmap(bmd));
	}
}

Here we have moved the storage of the student XML from a temporary field of our class to the callback that will be using it. The callback can now simply use what it is provided rather than having to know where to look up the pertinent information. It also unburdens the callback from the duty of cleaning up the temporary field. The callback no longer needs to concern itself with cleanup; it simply does the work that it is supposed to do.

So how is all of this achieved. Well, closures make this a complete snap in AS2 and AS3. I will provide the AS3 version of the class here but leave creation of the AS2 version as an exercise for those still concerned with using it. The differences are mostly syntactical anyhow. Here is the AS3 version:

package
{
	/**
	*   A utility class to create curried functions. These are functions that
	*   will call another function and add extra parameters that you define
	*   when you create the curried function. For example:
	*       CurryFunction.create(this, foo, 3, 5)();
	*       private function foo(val:Number, val2:Number): void
	*       {
	*           // val is 3, val2 is 5
	*       }
	*   While it is harmless to do so, it is pointless to directly instantiate
	*   a CurryFunction.
	*   @author Jackson Dunstan (jackson@jacksondunstan.com)
	*/
	public class CurryFunction
	{
		/**
		*   Create a curried function
		*   @param thisArg The object to call the function on, usually "this" or
		*                  "null" for dynamic functions, static functions, or
		*                  functions outside a class.
		*   @param func Function to call
		*   @param extraArgs Arguments to curry in. These will be passed after
		*                    the arguments normally passed to the function.
		*/
		public static function create(thisArg:Object, func:Function, ...extraArgs): Function
		{
			return function(...args): *
			{
				return func.apply(thisArg, args.concat(extraArgs));
			};
		}
	}
}

For those new to functional programming, this can be a little mind-bending. It’s important to remember here that you never actually have a CurryFunction object. CurryFunction is simply a class that is used to create curried functions. CurryFunction creates an in-between function that will call your actual function and pass not only the arguments it got but also all the arguments that you are “currying in”. Here is an example app that tests out CurryFunction:

package
{
	import flash.text.*;
	import flash.display.*;
 
	public class MyApp extends Sprite
	{
		private static var logger:TextField = new TextField();
 
		public function MyApp()
		{
			logger.autoSize = TextFieldAutoSize.LEFT;
			logger.multiline = true;
			addChild(logger);
 
			CurryFunction.create(this, foo, 3, 5)();
			log("goo returned: " + CurryFunction.create(this, goo, "korma")());
			CurryFunction.create(
				null,
				function(bool:Boolean, integer:int): void
				{
					log("void dynamic func: bool=" + bool + ", integer=" + integer);
				},
				true,
				42
			)();
			log("non-void dynamic func returned: " + CurryFunction.create(
				null,
				function(num:Number, x:XML): RegExp
				{
					log("non-void dynamic func: num=" + num + ", x=" + x);
					return new RegExp("^monkey$");
				},
				Math.PI,
				<person><first>Jackson</first><last>Dunstan</last></person>
			)());
		}
 
		private function foo(val:Number, val2:Number): void
		{
			log("foo: val=" + val + ", val2=" + val2);
		}
 
		private function goo(str:String): String
		{
			log("goo: str=" + str);
			return str;
		}
 
		public static function log(o:*): void
		{
			logger.appendText(o + "\n");
		}
	}
}

And the results, all as expected:

foo: val=3, val2=5
goo: str=korma
goo returned: korma
void dynamic func: bool=true, integer=42
non-void dynamic func: num=3.141592653589793, x=<person>
  <first>Jackson</first>
  <last>Dunstan</last>
</person>
non-void dynamic func returned: /^monkey$/

One downside to currying is that it is not as fast as regular functions. It makes one dynamic function call (the call through a Function variable) into two dynamic function calls (the middle-man function) and also does an Array.concat(), which is dynamic and causes a bit of memory allocation. All of this is necessary in order to do the currying, but is certainly not fast. I think the best argument against this downside is that if you are using dynamic function calls rather than my runnable technique, you probably don’t care much about performance anyhow. You may care about it elsewhere in your app, but not in the area that you’re using dynamic function calls.

As I said in the opening, this is a very valuable tool to have available to you. It will save you a lot of typing and therefore increase your productivity in many cases. In my daily AS3 programming I use currying very often, always in non-performance critical areas of my code. I recommend to you all that you add the CurryFunction class to your codebase. If you never use it, it will not be compiled into your SWF and you will have lost nothing. I believe that just knowing that the tool is there for use will remind you that it would be handy some day. On that day you will use it and be just a little bit more productive. Enjoy!