3

Here's the problem (called "Compose functions (T Combinator)" on codewars.com, in case you want to try it out in the original environment):

Let's make a function called compose that accepts a value as a parameter, as well as any number of functions as additional parameters.

The function will return the value that results from the first parameter being used as a parameter for all of the accepted function parameters in turn. If only a single parameter is passed in, return that parameter.

So:

var doubleTheValue = function(val) { return val * 2; }
var addOneToTheValue = function(val) { return val + 1; }

compose(5, doubleTheValue) // should === 10
compose(5, doubleTheValue, addOneToTheValue) // should === 11

Here was one of the possible solutions:

var compose = function(initialValue) {
  var functions = Array.prototype.slice.call(arguments, 1);
  return functions.reduce(function(previousResult, func){
    return func.call(this, previousResult);
  }, initialValue); 
}

Why do we need to return func.call(this, previousResult) rather than just func(previousResult)? The latter only works in some cases. What will "this" default to without the call?

Zack Gao
  • 568
  • 1
  • 4
  • 14

3 Answers3

2

Why do we need to return func.call(this, previousResult) rather than just func(previousResult)?

We don't really. this is not the this value of the compose function (what the author probably intended), but of the reduce callback - where it is specified to be undefined.

What will "this" default to without the call?

undefined as well, see Why is "this" in an anonymous function undefined when using strict?.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Hi Bergi, you said that we don't really need to return func.call(this, previousResult), but if I change the code to just func(previousResult), then it does not pass the exercise. Any insight on why this might be? – Zack Gao Jan 28 '14 at 05:15
  • Unfortunately that link requires a login, and I'm not familiar with codewars. But it might always be that an answer is incorrect :-) Ask the creator of the exercise! Also you might be interested in the question [Is there a reason why `this` is nullified in Crockford's `curry` method?](http://stackoverflow.com/q/21002417/1048572), where is explained how `this` should be irrelevant in functional programming. – Bergi Jan 28 '14 at 22:41
0

In strict mode, this will be undefined since there is no calling context.

In non-strict Javascript it will be the global object (window in a browser).

Paul
  • 139,544
  • 27
  • 275
  • 264
  • That partly clarifies things for me, but what does setting this as "this" do in the given solution? If I passed compose only functions that did arithmetic operations, then I wouldn't need to use call. I can think of a few examples of functions where I would have to use call, in the sense that having an undefined this would screw things up, but I don't see why the passing this to the call makes everything okay? – Zack Gao Jan 28 '14 at 04:11
  • If you need to access other `functions` in the `window`, how would your call understand what is cached and whatnot looking for only `function name` **rather than** `window` -> `function name`? – Nicholas Hazel Jan 28 '14 at 04:57
  • Sure I follow that, but where in the code would I need to access other functions in the window? Each func is being passed by the reduce and they exist in that scope? – Zack Gao Jan 28 '14 at 05:18
0

Why do we need to return func.call(this, previousResult) rather than just func(previousResult)?

this defaults to our window.

Basically, we're giving it a secondary value in order to further our progression down the line.

If you were to call simply previousResult, the JS doesn't know where to look to find such a thing. Your are referencing the window if you don't call a prior parameter. This is very common in most OOP languages. You can't look for your value IN window without further defining that you want something IN window.

Essentially, we are just providing a bogus variable in order to get to the next step in the chain. You will see this a lot with Python and Ruby code.

The reason you set this is because this will equal the parent window, then you know you can find the next variable within that particular parameter.

Simple Example: It's sort of like trying to call a variable in a different function. Just doesn't work without defining your scope first.

Nicholas Hazel
  • 3,758
  • 1
  • 22
  • 34
  • Thanks :-) Hopefully that made sense. – Nicholas Hazel Jan 28 '14 at 04:23
  • You said "If you were to call simply previousResult, the JS doesn't know where to look to find such a thing". But previousResult is a parameter in the callback function for reduce, so wouldn't it be known? – Zack Gao Jan 28 '14 at 05:14
  • You'd be surprised how `Javascript` handles data. It still has quite a few quirks. And yes, you **would** think, but unfortunately calling `any data` on it won't work in that situation. Let me dig up a reference for you :-) – Nicholas Hazel Jan 28 '14 at 05:21