Partial Applications with Javascript & AS3

Perhaps the title of this article should be “Why Partial Applications are used more than Function Currying“. Readers should note that this article is essential a continuation of my earlier article “Function Currying in Javascript & AS3“. If I want to curry an existing function in the correct order or I want to write Functional code then Function Currying works great. Often, however, I use a sibling of Function Currying: Partial Applications.

Earlier today I updated my article Function Currying with Javascript with sample code. I added an elegant sample that demonstrates the use of Function Currying with Angular $q and data services. Function Currying has powerful usages and should not be deprecated without an appreciation for its versatility. Currying can be a paradigm shift for developers… so be prepared for your head to hurt!

Another way to learn about about Partial Application and Function Currying is to watch video below!

I demonstrate concepts using existing code and iteratively refactor that code to make it more DRY and more terse. As part of that process, I incrementally implement solutions using closures and – finally – partial application techniques vital to solving my refactoring issues.

 


Partial Application (with Javascript)

For clarity, let me first demonstrate some JavaScript solutions using Partial Applications.

Consider the scenario where I need to enhance a Logger instance with extra functionality. I need to substitute the standard log functions with my own log functions. But internally I will call the ORIGINAL log functions with the output `enhanced`. In this case, I want to use Partial Application to keep my code terse and DRY.

function enhanceLogger( $log )
{
        /**
         * Partial application to pre-capture a logger function
         */
    var prepareLogFn = function( logFn )
        {
            /**
             * Invoke the specified `logFn<` with the supplant functionality...
             */
            var enhancedLogFn = function ( )
            {
                var args = Array.prototype.slice.call(arguments),
                    now  = DateTime.formattedNow(),

                    // prepend a timestamp to the original output message
                    args[0] = supplant("{0} - {1}", [ now, args[0] ]);

                logFn.call( null,  supplant.apply( null, args ) );
            };
             
            // Special... only needed to support angular-mocks expectations
            enhancedLogFn.logs = [ ];

            return enhancedLogFn;
        };

    $log.log   = prepareLogFn( $log.log );
    $log.info  = prepareLogFn( $log.info );
    $log.warn  = prepareLogFn( $log.warn );
    $log.debug = prepareLogFn( $log.debug );
    $log.error = prepareLogFn( $log.error );

    return $log;
};

Here prepareLogFn is a Function that generates another Function enhancedLogFn which is substituted in place of the original $log logger function.

Notice that both the Function Currying and Partial Application techniques return Functions… these are functions that generate functions!

As you can see, Partial Application are not that difficult and can be VERY useful. Maybe you were already doing this and did not realize that such solutions are called partial applications or function currying.


AngularJS & Databinding

The AngularJS IoC framework supports templating, databinding, and dependency injections. Custom services and controllers can modify model data. And those changes are propagated to the UI layers using data binding and templates.

If I create custom Dataservices with promise-returning APIs, then the asynchronous responses to those DataServices are `outside` the AngularJS engine… and the callbacks may need to notify AngularJS to update the DOM UI. Because my service callbacks may modify scope variables and other model data, data-bindings need to be triggered to update the GUI.

AngularJS does not use a polling mechanism or complication model proxies to watch the data models. Instead AngularJS provides a  $apply()  function to force a data scan and check for changes in data models… changes that have not yet propagated to the GUI/DOM elements.

Here is sample code that calls $apply() for both success and fault responses to the saveUser() dataservice call.

Version #1: Standard Approach
function saveUser( successHandler, faultHandler, $rootScope, $log )
{
  var onResponse = function( response ) 
      {
        $log.debug( "onResponse_saveUser()" );

        // Wrap callback in $apply() to trigger AngularJS
        // to scan for `dirty` data after the successHandler() finishes...
        $rootScope.$apply( function()
        {
          successHandler( response );
        });
      },
      onFault = function( fault )
      {
        $log.debug( "onFault_saveUser()" );

        // Wrap callback in $apply() to trigger AngularJS
        // to scan for `dirty` data after the faultHandler() finishes...
        $rootScope.$apply( function()
        {
          faultHandler( fault );
        });
      };

  // Save user information and update UI via <xxx>Handler(s)
  userDelegate
    .save( user )
    .then( onResponse, onFault );
}

Notice my Promise handlers (above) had to manually invoke $apply() within the two (2) handlers… and there is a significant amount of similar code. In fact, such code (above) should be considered `poorly finished` and a FAILURE; at least from a DRY perspective.

Version #2: Refactored with Partial Applications

Now, I can use Partial Application and refactoring to extract common behaviors, identify generic arguments, and create better easier-to-maintain code.

The common Behaviors are:

  1. Generate a Function expecting a single argument,
  2. Logging, and
  3. Calling $apply().

And the common Arguments needed are:

  1. Callback handler, and
  2. Log message.
function saveUser( successHandler, faultHandler, $rootScope, $log )
{
    /**
     * Partial Application to capture specific callback and logging message
     */
  var prepareHandler = function( handler, logMsg )
      {
        // Return a generated function...
        return function( response )
        {
          $log.debug( logMsg );

          // Wrap callback in $apply() to trigger AngularJS
          // to scan for `dirty` data after the successHandler() finishes...

          $rootScope.$apply( function()
          {
            handler.call(null, response );
          });
        }
      };

  // Save user information and update UI via <xxx>Handler(s)

  userDelegate
    .save( user )
    .then( 
      prepareHandler( successHandler, "onResponse_saveUser()" ),
      prepareHandler( faultHandler,   "onFault_saveUser()"    )
    );
}

Above, I centralized logic into prepareHandler to build specific handlers for my Promise resolve and reject response.

This is not just code refactoring… this is refactoring AND using Partial Applications to pre-capture arguments or values for later use. And this final result is what I consider to be DRY, terse, and good code.

Version #3: Refactored with Curry

Finally – for completeness – I will modify Version #2 above to not use Partial Application. Now I want to use the Function Curry technique (@see Function Currying with Javascript)

function saveUser( successHandler, faultHandler, $rootScope, $log )
{
    /**
     * Partial Application to capture specific callback and logging message
     */
  var prepareHandler = curry( function( handler, logMsg, response )
      {
          $log.debug( logMsg );

          // Wrap callback in $apply() to trigger AngularJS
          // to scan for `dirty` data after the successHandler() finishes...

          $rootScope.$apply( function()
          {
            handler.call(null, response );
          });
      });
 
  // Save user information and update UI via <xxx>Handler(s)
 
  userDelegate
    .save( user )
    .then( 
      prepareHandler( successHandler, "onResponse_saveUser()" ),
      prepareHandler( faultHandler,   "onFault_saveUser()"    )
    );
}

Only the prepareHandler() implementation has changed to use curry(). Using curry() I was able to eliminate the nested closure solution used in Version #2.

Are you starting to see similarities and uses of both Function Currying and Partial Applications?


Partial Application (with AS3)

Now let’s explore Partial Application techniques in ActionScript. I will demonstrate functionality similar to Function Currying: Versions #3 but without using Function Currying; instead I will use custom functions and Partial Application techniques.

/**
 * Search and filter list of cars based on searchTerm criteria
 */
public filterByCriteria( allCars:Array, searchTerm:String, caseSensitive:Boolean ) : ListCollectionView
{
      /**
       * Function currying to capture search criteria and caseSensitive flag.
       * @return Function 
       */
      function buildPartial( searchTerm:String, toLowerCase:Boolean=true ) : Function 
      {
            function alwaysTrueFn (src : * ): Boolean 
            { 
              return true; 
            };

            function hasSearchTermFn (src : * ): Boolean 
            {
              var targetToSearch : String = String(src) || "";
              if ( toLowerCase ) targetToSearch  = targetToSearch.toLowerCase();

              return (targetToSearch.indexOf( searchTerm ) > -1);
            };

          searchTerm ||= "";
          if ( toLowerCase ) searchTerm = searchTerm.toLowerCase();  

         return  !criteria.length ? alwaysTrueFn : hasSearchTermFn;
      }

  /**
   * Instead of function currying, we use a custom function to capture 
   * the `searchTerm` argument and caseSensitivity. This is called a 
   * Partial Application since it returns another Function... implying
   * that the final function is only `partially` ready.
   */
  var foundIn     : Function = buildPartial( searchTerm, caseSensitive );

  var collection  : ListCollectionView =  new ArrayCollection( allCars );
  var carFilter   : Function = function (car:CarVO ) : Boolean 
      {
          if ( car.hidden )                   return false;
          if ( !search || searchTerm == "")   return true;

          if ( foundIn( car.title ))          return true;
          if ( foundIn( car.owner.name ))     return true;
          if ( foundIn( car.description ))   return true;
   
          return false;
      };
   
  
  collection.filterFunction = carFilter;
  collection.refresh();

  return collection;
}

Notice that we are not currying an Function to capture argument values. Instead we used a custom function buildPartial to capture the searchTerm and case flag and then return 1 [of 2] internal custom Functions. This Partial Application technique is very useful when I need more flexibility [than is available in Currying] especially if I want to have custom code wrapped in a closure.


Summary

I should note that I almost NEVER produce DRY code upon the first pass… DRY code is the result of iteratively refactoring during code implementation. Multi-pass refactoring makes my code terse and DRY… it ultimately means my debugging is easier and the code is readable. And – most important of all – the Partial Application technique has proven to be invaluable… almost used daily in my code.

 

Tags: , , , , ,

Partial Applications with Javascript & AS3

5 Responses

  1. Hello there, You have done a great job. I’ll certainly digg it and personally recommend
    to my friends. I am sure they’ll be benefited from
    this website.

    view site... February 27, 2016 at 3:03 pm #
  2. You actually make it appear really easy with your
    presentation but I in finding this matter to be actually something that I think I’d
    by no means understand. It sort of feels too complex and extremely large for me.

    I’m looking ahead to your next post, I will attempt to get the hang of it!

    visit here December 25, 2015 at 5:36 am #
  3. Thanks for your personal marvelous posting! I quite enjoyed reading it, you will be a
    great author.I will be sure to bookmark your blog
    and may come back in the future. I want to encourage you to continue
    your great posts, have a nice weekend!

    google plus app for blackberry March 8, 2014 at 2:31 pm #
  4. Great post, thanks!

    Ken Rogers October 20, 2013 at 11:19 am #
Trackbacks/Pingbacks
  1. Function Currying in Javascript & AS3 | The Solution OptimistThe Solution Optimist - October 17, 2013

    […] I encourage you to continue Part 2: Partial Applications with Javascript & AS3. […]

Leave a Reply