-2

While reading about Javascript First Class Functions here at SO, I came across this link: What is meant by 'first class object'? wherein I found this interesting example:

var men = function (objectOfAdmiration) {
  return objectOfAdmiration();
};
men.isSweetHeart = true;

var women = function (objectOfAdmiration) {
  return objectOfAdmiration();
};
women.isSweetHeart = true;

var aliens = function (objectOfAdmiration) {
  return objectOfAdmiration();
};

function like(obj){
  if (obj.isSweetHeart) {
      return function (){ return "Holy TRUE!"}; 
  }
  else {
      return function (){ return "Holy CRAP!"};
  }
}

alert("Men like women is " + men(like(women))); // -> "Holly TRUE!"
alert("Women like men is " + women(like(men))); // -> "Holly TRUE!"

alert("Men like aliens is " + men(like(aliens))); // -> "Holly CRAP!"
alert("Aliens like women is " + aliens(like(women))); // -> "Holly TRUE!" 

I need someone to explain this code, the way things r getting executed here. Especially the expression men(like(women)) and/or women(like(men)). How is this working out to produce the final result...

Thanks in advance

Mani Malhotra
  • 97
  • 1
  • 3
  • 12
  • I'm aware of the PEMDAS rule. What I need to know is what happens when 'like(women)' expression which returns a functions is fed to the function men()? Thanks – Mani Malhotra Jul 27 '17 at 19:54

1 Answers1

2

Just remember your "order of operations" from high school algebra:

  • Parenthesis
  • Exponents
  • Multiplication
  • Division
  • Addition
  • Subtraction

Parenthesis are always evaluated first. And, in the case of an expression having nested sets of parenthesis, the inner set is evaluated before the outer ones.

So, with:

men(like(women))

The like function is first invoked with the value of the women variable passed to it.

Whatever that function returns is then the argument that is passed to the men function. Like this:

men( result of calling like(women) )

And, women(like(men))

is the same idea, just reversing which one is invoked first.


So, let's take this one step at a time.

  • It's very important that you first recognize that the men, women and alien functions are actually all identical. They simply invoke whatever you pass to them and return that result (which in this case will always be another function). You can infer this because all they do is stick a set of parenthesis on the end of the input argument. They each, therefore are expecting a function to be passed (because that's the only thing you can invoke).

So, let's pay less attention to those functions and more attention to the like function because that is the one that returns different functions to its caller.

Read the inline comments for explanations:

// Function expression that sets men to hold a function 
var men = function (objectOfAdmiration) {
  // This function is expecting a function to be passed to it
  // because all it does is invoke what is passed and only 
  // functions can be invoked.
  return objectOfAdmiration();
};

// Treat men like an object now and give it an isSweetHeart property with a value of true
men.isSweetHeart = true;

// Function expression that sets women to hold a function 
var women = function (objectOfAdmiration) {
  // This function is expecting a function to be passed to it
  // because all it does is invoke what is passed and only 
  // functions can be invoked.
  return objectOfAdmiration();
};

// Treat men like an object now and give it an isSweetHeart property with a value of true
women.isSweetHeart = true;

// Function expression that sets alients to hold a function 
var aliens = function (objectOfAdmiration) {
  // This function is expecting a function to be passed to it
  // because all it does is invoke what is passed and only 
  // functions can be invoked.
  return objectOfAdmiration();
};

// Function declaration for like.
// This function is expecting an object that has an isSweetHeart property.
// Since we have multiple types of objects that support that property, this
// function is polymorphic
function like(obj){
  if (obj.isSweetHeart) {
      // If the men or women objects are passed, this will be returned
      return function (){ return "Holy TRUE!"}; 
  }
  else {
      // Anything that doesn't have the isSweetHeart property or does
      // but that property has a "falsey" value will end up here
      return function (){ return "Holy CRAP!"};
  }
}

// Invoke like(woman)...
// since the woman object does have an isSweetHeart property and that
// property has a value of true, the function that will return "Holy TRUE!"
// when it is invoked is returned.

// That function is then passed to the men function, which recieves it under
// the parameter name of "objectOfAdmiration".

// Invoking that function outputs "Holy TRUE!"
alert("Men like women is " + men(like(women))); // -> "Holy TRUE!"

// This line does just about the same as above, but in reverse and
// because the men and women functions are the same, the same output
// is produced.
alert("Women like men is " + women(like(men))); // -> "Holy TRUE!"

// Same general procedure as before, but since aliens do not even 
// have an isSweetHeart property, a different function is returned
// for further processing.
alert("Men like aliens is " + men(like(aliens))); // -> "Holy CRAP!"

// This is essentially the same as the men(like(women)) function call
// except that the result of like(women) is passed to aliens, which 
// Simply invokes that function.
alert("Aliens like women is " + aliens(like(women))); // -> "Holy TRUE!" 
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • Thanks Scott for the reply, I'm aware of the PEMDAS rule. What I need to know is what happens when 'like(women)' expression which returns a functions is fed to the function men()? – Mani Malhotra Jul 27 '17 at 19:53
  • Thanks for bearing with me Scott... I'm trying to get my head around this whole 'returning a function' and 'invoking a function' thing.... Let me work on what u explained and will get back to u... Thanks again.. – Mani Malhotra Jul 27 '17 at 20:04
  • @ManiMalhotra I've updated my answer to provide a walk through. – Scott Marcus Jul 27 '17 at 20:13
  • Thanks a ton Scott. This was a huge help from you. Now I can savor different bits of this code. Your explanation really helped... – Mani Malhotra Jul 28 '17 at 15:10
  • @ManiMalhotra You're welcome. Keep in mind that in the real world, the `men`, `women`, and `aliens` functions wouldn't be written as separate functions since they are all identical. Instead a single function called, say `lifeForm` would be created and then, using object inheritance, a `men`, a `woman` and an `alien` object would be defined that inherits from it. – Scott Marcus Jul 28 '17 at 15:12
  • 1
    Will look into Object Inheritance now... Thanks again Scott. People like u make this awesome community so AWESOME... Regards... – Mani Malhotra Jul 28 '17 at 17:27