Why isn't my function a function?

Hi,

I’d really appreciate some help with this problem. I’ve been working through the Lodash assignment in the javascript course and I got completely stuck on the findKeys one, so I ended up viewing the solution. I’ve been writing my sections of code in Visual Studio but for some reason the responses that work in the Codecademy console don’t seem to work in Visual Studio. The Lodash solution is shown directly below and underneath that I’ve shown how I’ve adapted it to be a free-standing function in VS. When I run it in VS I get a message saying “predicate(value) isn’t a function”. I’m really keen to figure out where I’m going wrong because this part of the assignment really threw me and I really want to master the skills needed to do it. Thanks anyone who can help!

findKey(object, predicate){ for (let key in object) { let value = object[key]; let predicateReturnValue = predicate(value); if (predicateReturnValue) { return key; } } undefined return undefined; }
function findKey (object, predicate) { for (let key in object) { let value = object[key]; let predicateReturnValue = predicate(value); if (predicateReturnValue) { return key; } }; undefined return undefined; };

Hi,
predicate is a function in the CC environment because CC defined it for you and passes it as an argument to the function call. If you want the code to work in your local environment, you have to define a predicate function as well.

1 Like

Thanks mirja,

That makes sense but I’ve been messing around trying to define the predicate function for an hour and made very little progress. Also, I read this code from another user (Pauwau, here: Lodash project .findKey() confirmation), which is basically doing the same thing. So in both solutions, is it that you have to write a function which has the name of the second parameter of the findKey function (in this case func)?

const findKey = (obj, func) => { for (let key in obj) { if (func(obj[key]) == true) { return key; } else { return undefined; }; }; } var users = { 'barney': { 'age': 36, 'active': true }, 'fred': { 'age': 40, 'active': false }, 'pebbles': { 'age': 1, 'active': true } }; console.log(findKey(users, 'active'));
1 Like

Define a predicate function

const predicate = () => {
  // your solution 
}

the name of the parameter can be different from the function name, but inside the function it has to be referenced by the parameter name

const findKey = (obj, func) => {
    for (let key in obj) {
        //your solution
    }
}

Pass the predicate function as a 2nd parameter

console.log(findKey(users, predicate));

If you want us to help you with the predicate function, we need the instructions, please provide a link to the lesson.

1 Like

Hi yes, sorry, first time post. The link is: https://www.codecademy.com/paths/full-stack-engineer-career-path/tracks/fscp-javascript-syntax-part-ii/modules/fecp-practice-javascript-syntax-arrays-loops-objects-iterators/projects/lodash and it’s the findKeys section

1 Like

So what we know about the predicate function:

a function that returns a boolean value

[the findKey function] calls the predicate function with the value

the first key that has a value that returns a truthy value from the predicate function

What does it mean:

  1. The predicate function takes a parameter
  2. The predicate function returns either true or false
  3. The predicate function checks if the given argument (a value from an object property) matches certain criteria (up to you)
const predicate(value) {
 if( value matches criteria ) {
   return true
 }
 else {
  return false
 }
}
1 Like

Hi,

thanks for this. I think I’m going to come back to this since I’m exceeding the brief for the activity. The real lesson here is to read the instructions more carefully, because it does clearly say " Call the provided predicate function with the value at that key." Anyway, I appreciate your help.

T

Sure, if you do the lesson in the CC environment, you do not need to write that predicate function yourself. But if I understood correctly you did it in your local surrounding. Then you do.
It is also useful to understand what the predicate function does in order to understand what your findKey function is supposed to do.

Thanks, you’re right, I need to see this through. So…

Still unbelievably confused. My understanding so far is that “predicate”, the parameter in the findKeys function, could be the name of an actual function so you could pass an actual function name as your answer.

So for example I could write a function called “predicateFunction” separately from findKeys and then I can call find keys like this:

findKeys(objectName, predicateFunction).

Okay, so now I don’t get the function error message, but also, my predicate function isn’t working…

var users = { 'barney': { 'age': 36, 'active': false }, 'fred': { 'age': 40, 'active': false }, 'pebbles': { 'age': 1, 'active': true } }; //predicateFunction const predicateFunction = (value) => { for (let key in value) { let value2 = value[key]; if (value2) { return true; } else { return false; } } } //the exemplar function for the findKeys function in the Lodash activity function findKey (object, predicate) { for (let key in object) { let value = object[key]; let predicateReturnValue = predicate(value); if (predicateReturnValue) { return key; } }; undefined return undefined; }; //attempting to call the function console.log(findKey(users, predicateFunction)); /*returns 'Barney' even though I've changed the settings for Barney to 'active': false from console.logging I can tell that the predicateFunction is reading the nesting object as a whole (this bit: { 'age': 36, 'active': false }) which makes sense because by calling predicateFunction anonymously, I'm not passing any argument about what I'm actually looking for in the object, but... */

If I run the code trying to call my search term (‘active’) within the function argument, it just goes back to saying that “predicate isn’t a function”

console.log(findKey(users, predicateFunction(‘active’)));

So confused!!

Your object “users” is passed to the function “findKey”. That function iterates through the object. For each iteration the predicate function is called with just one value. Which means there is nothing to iterate through in the predicate function. The predicate function just needs to deal with a single value.

In a previous post I wrote that the argument passed to the predicate function is a key – actually it is the value related to the key. I corrected that. Step 28.3 says:

  1. Call the provided predicate function with the value at that key.

Okay brilliant, so i can simplify my predicate function but this is obviously too simple…

const predicateFunction = (value) => { if (value === true) { return true; } else { return undefined; } }

because it’s not working.

Also I get what you mean that I don’t need to iterate through the object because the predicate deals with one value at at a time, but my concern is that the one value in question may itself be an object. For example here…

var users = { 'barney': { 'age': 36, 'active': false }, 'fred': { 'age': 40, 'active': false }, 'pebbles': { 'age': 1, 'active': true } };

…with the code as it stands, the first value being passed to the predicate is {‘age’: 36, ‘active’: false}, which is itself an object. I feel like I need some sort of code that means: does this nested object contain a true statement?

Keep it simple. Don’t put too much effort in your predicate function or the object as this is whatever CC provides. And if they provide a nested object they will handle the distinction in their predicate function.

So just provide an object with properties that just hold strings or numbers like

var users = {
    barney: 36,
    fred: 40,
    pebbles: 1
};

The keys don’t need to be wrapped in quote marks if you don’t add spaces to them.

The predicate function must return a boolean. undefined is not a bool. Return true or false only.
Your predicate function may return true if the user is adult and false if not, for example.

Okay, so all I’m aiming for is to pass the values of an object through the predicate function, where the predicate function is coded to assess for just one condition, ie: if I take your suggestion, the predicate function itself will be coded to check whether users are adults and that’s the only check it’ll be able to make?
That sounds more manageable, thanks.
Thanks for all your help so far!

1 Like

Okay, I think I’ve mastered this to my satisfaction. I left in all the console.log seeds I planted to oust bugs :slightly_smiling_face:

//predicate function.... const adultivity = (value) => { if (value >= 18) { //console.log('adultivity ran if'); return true; } else { (value < 18) //console.log('adultivity ran else'); return false; } } //findKeys function function findKey (object, predicate) { for (let key in object) { let value = object[key]; //console.log(`object key from findKey was ${object[key]}`); let predicateReturnValue = predicate(value); //console.log(`predicateReturnValue from findKey was ${predicateReturnValue}`); if (predicateReturnValue === true) { //console.log('findKey ran if'); return key; } }; //console.log('findKey ran undefined'); undefined return undefined; }; //object to scan const usersSimplified = { bambam: 2, pebbles: 1, barney: 36, fred: 40 } //function call console.log(findKey(usersSimplified, adultivity)); //expected output: 'barney'

Thanks for all your help!

May I ask why you have undefined and returning undefined at line 8?

1 Like

Hi, not really sure myself tbh. That was the code as explained in the video you could watch if you got stuck. My focus in this thread was more about figuring out the predicate function. I get what you mean though, it’s not clear exactly what the value is of saying: “If it’s undefined then it’s undefined”