1

I'm trying to write a function utilizing callback that will mimic this behavior:

var fullName = function (firstName, lastName) {
  return firstName + ' ' + lastName;
};

var michaelName = partial(fullName, 'Michael');
michaelName('Moore'); // 'Michael Moore'
michaelName('Jackson'); // 'Michael Jackson'

I was stuck for a while trying to write a function named partial that will call back the function fullName but finally got it to work but am not sure if it's a) correct and b) exactly what is happening.

var partial = function(callback, firstName) {
    var innerFunction = function(lastName) { //I declared an inner function in order to create a closure of the variable lastName
      return callback(firstName, lastName); //The closure is completed (or is it only then created?) by returning the function argument named callback taking firstName and lastName as arguments
    };
    return innerFunction; //the function partial will finally return the closure, function innerFunction
}

var michaelName = partial(fullName, 'Michael');
console.log(michaelName('Moore')); //Michael Moore

Is what I've written in defining the function partial the general pattern for writing a callback? If not, can someone show/point me to where I can study this pattern? Is there any other way to refactor this callback so that it's cleaner? I wasn't sure if I needed to create a new innerFunction but when I did I finally got the behavior to work as intended. Is my reasoning in the comments to the code accurate? Would somebody mind stepping through my code and further explaining what is happening, why callback is returned from innerFunction and why partial returns innerFunction instead of callback? Much obliged.

duplode
  • 33,731
  • 7
  • 79
  • 150
phizzy
  • 936
  • 9
  • 26

3 Answers3

3

Yes, you've written that partial function exactly right.

I would avoid confusing yourself by using the term "callback" here. That word is usually used in a different context: to mean a routine which is called when something is done, or called for each element of an array by forEach, for example. Here, what you are passing in is simply an underlying function, which will be called along with an extra specified parameter when the returned function is called. You can also return the function directly so just

var partial = function(fn, firstName) {
    return function(lastName) {
        return fn(firstName, lastName);
    };
}

Is there any other way to refactor this callback so that it's cleaner?

Not really, other than as mentioned above. However, it could be made more general (see below).

I wasn't sure if I needed to create a new innerFunction but when I did I finally got the behavior to work as intended.

By definition, partial needs to return a function. That's its purpose. So yes, you have to create the function you are going to return. You could create it as a separate named function and then return it, as you did, or create it right in the return statement, as above.

Is my reasoning in the comments to the code accurate?

Not entirely:

I declared an inner function in order to create a closure of the variable lastName

but in fact this function is closing over firstName, the variable from the outer scope.

The closure is completed (or is it only then created?) by returning the function argument named callback taking firstName and lastName as argument

Different people have different ideas about the precise meaning of closure. Some would say that merely defining a function using a variable from an outer scope constitutes a closure. Others would say that it is not a closure, or at least it doesn't make sense to call it a closure, unless the function is "exported" (returned) for use from outside, as you are doing.

Would somebody mind stepping through my code and further explaining what is happening, why callback is returned from innerFunction and why partial returns innerFunction instead of callback?

callback is not being returned from innerFunction; the result of invoking it is. That's exactly how you need it to work: you want the function returned by partial to invoke the function you originally passed in. Returning callback directly from partial would not accomplish anything; you would just be returning the function you passed in.

So the overall flow is:

  1. You have some function like fullName, and you want to create another function that has the first argument "already filled in".

  2. Define the function partial which takes a function to fill in the argument for, and the argument to fill in.

  3. partial "remembers" the function to be called and the argument to fill in passed to it. It returns a function (which is what you want)

  4. You call the partial function returned from partial, which calls the original function with the pre-filled argument and one more passed into that function. That function (your innerFunction) can "see" the function to call (what you call callback) and the argument to fill in because it closes over them (it's a closure accessing those variables from the outer scope.

However, your partial is a bit limited. For one thing, it only handles one pre-filled argument. You might want to handle more. Also, it doesn't know how to pass through this to the innerFunction. You can solve those kinds of problems by doing:

function partial(fn, ...prefilledArgs) {
    return function(...additionalArgs) {
        return fn.call(this, ...prefilledArgs, ...additionalArgs);
    };
}

In the above, I've used the new ES6 "spread parameters" feature, because it's easier to read and write. In ES5, you need to use array functions to splice together the pre-filled arguments and additional arguments, which is not too much fun, as follows:

function partial(fn)
    var prefilledArgs = Array.prototype.slice.call(arguments, 1);
    return function() {
        var additionalArgs = Array.prototype.slice.call(arguments);
            return fn.apply(this, prefilledArgs.concat(additionalArgs));
    };
}

In the above, we "remember" the pre-filled arguments and assign them to the variable prefilledArgs, by removing the first element (fn) of the arguments pseudo-array using slice. Then, inside the inner function, we concatenate the pre-filled arguments and the additional arguments, and pass the whole list to the original function using apply, which is the way to call a function when you have the arguments in an array.

1

If you are looking for a cleaner way to write about code I would recommend using a Javascript closure. Here is a link explaining closures.

   var partial = function( firstName) {
       return function(lastName) { 
          return firstName + " " + lastName
        };
    }

    var michaelName = partial('Michael');
    console.log(michaelName('Moore'));

If you need a better understanding of callbacks Youtube has some great videos and here is a stack post that helped me to understand Callbacks.

A quote from the post

In plain English, a callback function is like a Worker who "calls back" to his Manager when he has completed a Task.

Community
  • 1
  • 1
Noel Kriegler
  • 509
  • 3
  • 11
  • 1
    You're missing the point. He's attempting to turn a function (in this case `fullName`) into a partial function. Not simply writing a generator. – slebetman Apr 22 '15 at 07:05
  • Yes @slebetman, I don't need to write partial as a generator-- I want to use `fullName` in writing the `partial` function. Is the way that I've done it correct? – phizzy Apr 22 '15 at 08:39
  • 1
    Ok, sorry I understand now. This [link](http://stackoverflow.com/a/9817905/3938031) might help you out. – Noel Kriegler Apr 22 '15 at 09:54
1

You've got the pattern right as I understand it, though your comments aren't quite right. Here's a more general-use implementation:

var partial = function(fn) {
    var appliedArgs = Array.prototype.slice.call(arguments,1);
    return function() {
        var moreArgs = Array.prototype.slice.call(arguments);
        return fn.apply(this,appliedArgs.concat(moreArgs));
    }
}

The main difference between this and yours is that it allows the passed-in function (callback, in yours) to have any number of parameters, and allows the partial application to satisfy any number of those...so long as they're being applied in order.

(Note that the MDN docs recommend against slicing arguments that way...while also providing an example of doing so. No double message there!)

Okay, let's step through your example:

First, you declare your base function - fullName(). No confusion there. This function has two arguments. The usefulness of partial application is that you might find yourself in a position where you know SOME of your parameters now, but won't know others until later. Partial application lets you apply some (thus 'partial application') of the parameters right now, getting back a function that has the same effect as your base function, but requires fewer parameters (because you've already supplied the others).

Next, you make the call var michaelName = partial(fullname,"Michael"); What you're asking for here is "give me a new function, called michaelName, that does what fullName would do if the first parameter were always 'Michael' and I only had to give it the last name". Once you understand that, the rest of the code starts to make sense.

partial() has to return a function, not a simple value, because that's what you're asking for - a new, simpler version of the callback you passed in. And what should that function do? It should give the result the callback would if called with 'Michael' and whatever second function it's given.

Here's your implementation again:

var partial = function(callback, firstName) {
    var innerFunction = function(lastName) { 
      return callback(firstName, lastName);
    };
    return innerFunction; 
}

And that's exactly what innerFunction() is. It's a function that feeds the already-known firstName and the new lastName into callback() and then returns the results.

S McCrohan
  • 6,663
  • 1
  • 30
  • 39