Skip to content

Advanced: Currying

Bert Loedeman edited this page Feb 1, 2016 · 2 revisions

Advanced topic: Currying

Currying, especially currying possibilities in Javascript, is explained in an excellent way by Douglas Crockford: http://www.crockford.com/javascript/www_svendtofte_com/code/curried_javascript/index.html (recommended article!). The sample code Douglas provides at the bottom of his post has been implemented in the AutoMapperTS implementation.

This wiki will not go into every currying detail, instead it will only highlight the usage possibilities for the AutoMapperTS implementation.

Brief functional introduction

Douglas Crockford describes currying as follows:

Currying is a useful technique, with which you can partially evaluate functions. What does this mean? Lets give an example.

Lets say we have a function myFunc, it takes two arguments, and adds these. I will now show some JavaScript, but not give the code to myFunc (that'll come later). This is just so you can get an idea, what it does.

alert(myFunc(2,2));      // alerts 4
var adds4 = myFunc(4);   // adds4, is now a function,
                         // which adds 4, to it's argument.
alert(adds4(5));         // alerts 9.

It's the second line, which is the key. If you give a curried function, less arguments, then it expects, it will give you back, a function, which has been fed the arguments you gave it, and will accept the remaining ones. In the example above, we first gave it 4 (myFunc(4)), and it was waiting for another number, and we gave it 9.

Usage samples

var mapFromKeyCurry = automapper.createMap(fromKey);

mapFromKeyCurry(toKey1)
	.forSourceMember('prop', (opts: AutoMapperJs.IMemberConfigurationOptions) => { opts.ignore(); });

mapFromKeyCurry(toKey2);

var result1 = automapper.map(fromKey, toKey1, source);
var result2 = automapper.map(fromKey, toKey2, source);
// arrange
var fromKey = '{FC18523B-5A7C-4193-B938-B6AA2EABB37A}';
var toKey1 = '{609202F4-15F7-4512-9178-CFAF073800E1}';
var toKey2 = '{85096AE2-92FB-43D7-8FC3-EC14DDC1DFDD}';

var source = { prop: 'Value' };

// act
var createMapFromKeyCurry = automapper.createMap(fromKey);

createMapFromKeyCurry(toKey1)
	.forSourceMember('prop', (opts: AutoMapperJs.ISourceMemberConfigurationOptions) => { opts.ignore(); });

createMapFromKeyCurry(toKey2);

var result1MapCurry = automapper.map(fromKey, toKey1);
var result2MapCurry = automapper.map(fromKey, toKey2);

var result1 = result1MapCurry(source);
var result2 = result2MapCurry(source);

// assert
expect(typeof createMapFromKeyCurry === 'function').toBeTruthy();
expect(typeof result1MapCurry === 'function').toBeTruthy();
expect(typeof result2MapCurry === 'function').toBeTruthy();

expect(result1.prop).toBeUndefined();
expect(result2.prop).toEqual(source.prop);
mapFromKeyCurry: (destinationKey: string) => AutoMapperJs.IAutoMapperCreateMapChainingFunctions = config.createMap(fromKey);

mapFromKeyCurry(toKey1)
	.forSourceMember('prop', (opts: AutoMapperJs.IMemberConfigurationOptions) => { opts.ignore(); });

mapFromKeyCurry(toKey2);