Freecodecamp: ES6 - Write Higher Order Arrow Functions - About Chaining, Needs Clarification

Created on 1 Jun 2018  路  31Comments  路  Source: freeCodeCamp/freeCodeCamp

Describe your problem and - if possible - how to reproduce it

Challenge ES6 - Write Higher Order Arrow Functions
The examples show moving from normal function to the ES6 arrow function. However, the challenge is about "chaining" multiple functions together. It is super unclear how the example code would lead one to chaining a filter and map function together. This is really a better discussion for the functional programming section.

Additionally, the filter function requires that users understand how to determine if a number is an integer or not. There is nothing in the prior curriculum which would make it clear to a new coder how to do this. While you do talk about the "parseInt" function, it's never used in the context of comparing a number to itself. A better filter function might be "positive numbers" instead, which is a much simpler comparison.

I was attempting to help someone understand this one today and I was initially flummoxed as to how to solve it.

Once I realized it was about chaining, I was able to write a solution like this:

const squaredIntegers = arr
    .filter(elem => elem == parseInt(elem))
    .map(elem => elem * elem);

I don't believe that there is another way to solve this using higher order functions and arrow functions. There is no solution in the seed file, so I'm not sure exactly what the authors had in mind.

In short, this challenge badly needs clarification and simplification. It may be entirely inappropriate for this section of challenges. I could see it after a new challenge called "How to Chain Higher Order functions" or something like that.

Add a Link to the page with the problem

https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/es6/write-higher-order-arrow-functions/

learn

Most helpful comment

I just reviewed the curriculum leading up to this challenge.

  1. There doesn't appear to be an introduction to the concept of a callback function or functions as first class object.
  2. No introduction to anonymous functions (except two challenges prior)
  3. No mention of either map or filter

All told, I think this challenge should just be removed or moved to the functional programming section.

All 31 comments

Look who is here..! I know this tracker is strictly for issue related discussion, but its awesome to see you here.

Thanks for the report.

Are these no longer being tagged/assigned? Is someone responsible for the new curriculum?

Hi Rex, sorry about the delay in getting back to you.

Yup.. you are right at the moment we do not have anyone to actively oversee the curriculum's quality. We would love some help though. Its been a little while since the new curriculum was first brought in (I mean added to the beta) by the contributors, so yeah it could use the polishing up.

I know of a lot of contributors who have done some great work like @ahmadabdolsaheb @mstellaluna and @scissorsneedfoodtoo recently, just to name a few off the top of my head.

The other thing is that us shipping the platform (splitting up the curriculum infra and the user backend) has broken the contributing pipeline. The new challenge infra is supper snappy and powerful BTW. So some real potential there, that we did not have previously. No more monkey patching console.log !!

The challenge and user schema has changed, the tooling has changed (for good though, which we will see in a few days hopefully, when we fix things for the local setup).

We are working toward improving to the DX for contributors, as soon as we have the production really stable for us to focus on the contributions. There has been a great surge in people wanting to contribute. We are just a little swamped the moment with the support and user priority issues.

P.S: Your baby Contributors Chat room is still the place where everyone hangs out, so if you would like to catch up, you know where to find us.

I would agree with this issue - I got real stuck on it knowing quite well how to use the array methods - it doesn't say anything about using .map and it is not used or taught at all up to this point - same with testing if it's an integer - that's not too tough to figure out I don't think, but it does complicate things - the challenge description only talks about using .filter and the instructions say...

Use arrow function syntax to compute the square of only the positive integers (fractions are not integers) in the array realNumberArray and store the new array in the variable squaredIntegers.

From those instructions it seems like the challenge wants you to use just .filter to accomplish this - challenges are supposed to teach a single thing, this one introduces too much and feels way too complicated - and it isn't clear to me what we are even supposed to be learning on this one

I just reviewed the curriculum leading up to this challenge.

  1. There doesn't appear to be an introduction to the concept of a callback function or functions as first class object.
  2. No introduction to anonymous functions (except two challenges prior)
  3. No mention of either map or filter

All told, I think this challenge should just be removed or moved to the functional programming section.

in general the whole es6 section seems to too advanced and/or complexly written (or at least some of it), and the javascript section as a whole seems a little scattered and not simple enough for beginners, or maybe just doesn't progress gradually enough or something - I want to suggest some rearranging of some sections/challenges but Im not sure on a better way yet - there's more than a few forum posts from campers struggling in this area of the curriculum

https://forum.freecodecamp.org/t/best-order-to-follow-js-modules/197705

Thanks for this post!
I was super confused trying to solve this as well and I've even been exposed to .map() and higher order functions previously. I thought for sure there would be a way to solve it with only .filter() because they haven't even said what the other functions do when you get to this exercise, or that it's possible to chain them together. I managed to solve it with a really ugly workaround, still using .map() but forgot about .parseInt() and that you can chain the functions...

const filteredIntegers = arr.filter(n => n > 0 && n%2 == 1|| n%2 == 0); 
const squaredIntegers = filteredIntegers.map(x => Math.pow(x,2));

Cheers!

Glad that I'm not alone. Please add more steps leading to that exercise. In the meanwhile, I'm going to leave ES6 module, move ahead and come back to it when I'll be able to understand. It's the very first time since I got started that I genuinely can say something negative about the curriculum...all the previous exercises made sense in the linear progression...not this one.

Maybe map, filter, reduce need to be explained beforehand. But chaining is not required and there are multiple solutions I suppose.

const squaredIntegers = arr.reduce((accumulator, currentValue) => {
  if(currentValue > 0 && currentValue % 1 === 0) {
    accumulator.push(currentValue * currentValue);
  }

  return accumulator;
}, []);

Hi! I'm a new coder who just got to this point in the challenges. It definitely took some serious google searching to figure out a solution, since .map(), .filter(), and .reduce() had not been previously mentioned. I also only really grasped that I could chain and nest functions like:

const squaredIntegers = arr.filter((num) => num > 0 && num == Math.floor(num)).map((num) => num * num);

due to having learned some through Grasshopper before I started with FCC. I think some challenge on that concept before this one would've been useful, as well as challenges on filter, map, and reduce.

I know the chaining isn't necessarily required... but at this point in the challenges where the theme seems to be on condensing code, IMO it's the perfect time to bring it up.

Or in the meantime, maybe we could just point the text for the map, filter, and reduce to their relevant challenges later on, or to relevant tutorials elsewhere on the internet if FCC doesn't currently have challenges for those concepts?

Hi All,
This one was a little fun to figure it out... Here are the steps I took to get the answer. I know it's a slower approach but I had to make sure that I could isolate each step before getting to the next one. I hope this helps!
<ol> <li>Bring all the code into a dev console. I use chrome (I always do this first).</li> <li>Change all the 'const' into 'var'. The reason for this is to keep copying and pasting the code to test it otherwise you will need to open a new tab to run it</li> <li>*Keep in mind that realNumberArray is what is being filtered!</li> <li>Only test that one value passes. Eg. - Test to make sure that the 4 goes through</li> <li>Once known that a value can be passed parseInt(arr) can be used</li> <li>Before using .filter with .map I isolated .map to pass a value, in order to make sure that the value does pass</li> <li>Combine .filter and .map</li> </ol>
/****************SPOILER ALERT************/




numbers in here correspond to the list above:







  1. var realNumberArray = [4, 5.6, -9.8, 3.14, 42, 6, 8.34];


    var squareList = (arr) => {


    "use strict";
    // change code below this line


    var squaredIntegers =
    realNumberArray


    .filter((arr) => arr === 4)//arr;


    // change code above this line


    return squaredIntegers;


    };



var squaredIntegers = squareList(realNumberArray);
console.log(squaredIntegers); /*answer will return 4/





___________________________________________________________________________

5.




var squaredIntegers =


realNumberArray


.filter((arr) => arr == parseInt(arr)) // value will return [4, 42, 6] once it's executed





________________________________________________________________________

7.




var squaredIntegers =


realNumberArray


.filter((arr) => arr == parseInt(arr))//arr;


.map((arr) => arr*arr);

I had to just skip it for now.

Agreed, I was chugging along fine and then hit this one which felt like a massive leap in difficulty from any of the previous. Mostly due that a lot of the concepts required to complete it were completely foreign as they had not been explained in prior lessons.

Skipping for now also.

here's my answer, i modified @Maarondesigns answer by chaining the functions but had to add the Math.sign(num) !== -1 to get rid of the -2

const realNumberArray = [4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2];
const squareList = (arr) => {
"use strict";
// change code below this line
const squaredIntegers = arr.filter((num) => num > 0 && num%2 === 1 || num%2 === 0 && Math.sign(num) !== -1 ).map( (num) => Math.pow(num, 2));
// change code above this line
return squaredIntegers;
};
// test your code
const squaredIntegers = squareList(realNumberArray);
console.log(squaredIntegers);

This is my solution:
// change code below this line
const squaredIntegers = arr.filter((int) => Number.isInteger(int) && int >=0).map(x => x * x);
// change code above this line
And this can work as well:
// change code below this line
const squaredIntegers = arr.filter((int) => int >=0 && int == parseInt(int)).map(x => x * x);
// change code above this line

const squaredIntegers = arr.filter((arr) => Number.isInteger(arr) && arr > 0).map((arr) => arr = arr * arr);

Just came to put my two cents in. I agree with the initial assessment of SaintPeter. I got totally lost on this one and I'm not new to programming, just new to JavaScript. I quickly realized there was a knowledge gap between what I know about these methods and what is expected to solve the problem.

@tommyprevatt, I agree, several more challenges need to be added to the ES6 section to fill in said knowledge gaps. @SaintPeter had some really great suggestions for possible challenge topics that could be added before this one, but I haven't taken the time to write them up yet.

If you have any suggestions for possible challenges you'd like to see before this one, please leave a comment. Or even better, please help us make a new challenge! There's still some time left in Hacktoberfest :+1:

im really feeling stupid for not being able to figure this one out :(

Is this still an issue? If so, then if I understand the problem correctly, the solution will be creating a text base explanation of how arrow functions work over ES5, emphasizing the chaining of arrow functions, right? I am pretty green PR-wise so not sure if I should just start, I don't want to do it wrong, etc.
If the above is correct I'll do this.

@chrisdel101 My suggestion would be to greatly simplify the problem such that it can be solved by changing a normal function definition into an arrow function definition. It's not even important that the output of the function be checked, just the syntax. Just make sure that the instructions line up and that the tests check for the correct syntax.

I think that would be the most direct solution.

I'd say go for it! Making these types of changes was how I got started. It's great experience!

I started on this. 2 problems:

  1. I can't see my changes in local dev. I posted about it here. It must be something like I am looking at the wrong file https://www.freecodecamp.org/forum/t/not-seeing-changes-in-local-dev-env/239352/3
  2. Where is the code for the tests? The YAML has this:
    testString: getUserInput => assert(getUserInput('index').match(/const\s+squaredIntegers/g), '<code>squaredIntegers</code> should be a constant variable (by using <code>const</code>).');
    Is this the actual test? What runs this? It's hard to read. What is the best way to work on functions inside a file like this?

I was going to re-write the problem a bit to check for syntax and change the tests. Not really sure how these tests within a markdown file work.

@chrisdel101, great that you started on this!

Seeing local changes is a bit of a process. First you need to reseed the db with npm run seed, then enter npm run bootstrap. When the last command is finished, enter npm run develop, then refresh the page when that's ready. You should be able to see your changes after that.

As for number 2, yes, that's the test. Tests come in pairs with a string for text and another for the testString. Text is what the user will see on the left side of the page before tests are run. The test string itself is made up of two parts--the first is the actual test, then the string after the comma which is shown in the console if the test fails.

As for the actual test suite, I believe we're using Chai. There's a cheat sheet that might help you write your tests here: https://github.com/freeCodeCamp/freeCodeCamp/blob/da0df12ab7b3bae46c2a376da246a6c499afd88b/guide/english/miscellaneous/chaijs-cheatsheet/index.md

There are a number of ways you could work with functions here. How were you thinking of rewriting the challenge? A lot of the times the tests look at the return value of the function. The third test currently does this:

- text: <code>squaredIntegers</code> should be <code>[16, 1764, 36]</code>
    testString: assert.deepStrictEqual(squaredIntegers, [16, 1764, 36], '<code>squaredIntegers</code> should be <code>[16, 1764, 36]</code>');

@scissorsneedfoodtoo Reran all the npm scripts and my changes are reflected after a seed, but my changes are still not reflected on save. I need to run npm run bootstrap to see them. Is there a way around this?

I'm familiar with Chai but will have to play around with the tests to fully get what is going on.

As for what I was going to re-write, just going to focus more on the syntax and remove the need for the function to be written in a particular way, i.e. it has to have an array named a certain way inside of it. This kind of change is what @SaintPeter suggested I do above.

Learning arrow functions is very similar to learning regex (which was excellent btw, kudos to the creators). One needs to slow down, have lots of practice runs of increasing complexity and then you'll get it. I am still quite far away from playing with Chai but if no one is actively working on this I'll give it a try. It can be broken up into three successively difficult challenges if that's OK...

@MoonCWang I've got a PR for this that's been there for already since November.

const squaredIntegers = arr.reduce((accumulator, currentValue) => { if(currentValue > 0 && currentValue % 1 === 0) { accumulator.push(currentValue * currentValue); } return accumulator; }, []);

Yes I UNDERSTAND most of this yet for the life of me I cannot understand why we truncate the decimal numbers or also current value % 1 === 0 so I have been looking at this problem for 1 hour at least... I do have strong math skills and understanding yet really modulus is just remainder yet what 1===0 so does this represent NAN I seem to be confused by word definitions relative to programming. I try to run the numbers through the function in my head yet this throws me off how am I filtering the decimal numbers.... I thought what if I can just pop that -2 of and make it not exist with pop() to no avail. Moving on now to much time on this.

I had lots of trouble with this too, until finding this post. I even tried to copy and paste the solution under "get a hint" so that I could work backwards and the hint doesn't pass the test.

people are just making it too complicated . here is my Solution it's very simple

const squaredIntegers = arr
  .filter(n => n % 1 == 0 && n>0)
  .map(n => n*n);

@IssamAth The issue, as described in my original post, and corrected by @RandellDawson's merge was that neither filter, map, nor chaining of functions had been introduced at that point in the curriculum. Presumably you are now completing this problem after it has already been moved to its new home.

It's not that people are making it "too complicated", it's that the groundwork had not been laid for this challenge in its original location.

Was this page helpful?
0 / 5 - 0 ratings