Exercise 1: skips :: [a] -> [[a]]
The nth list in the output should contain every nth element from the input list. For example, skips "hello!" == ["hello!", "el!", "l!", "l", "o", "!"].
The question UPenn Homework 3: skips function and it's associated answers inspired me to write a solution in Javascript. I used the opportunity to (finally) better understand high order array functions. If you would be so kind to critique:
- Code Layout, specifically if nesting
function skips()
makes any sense and why. - Do higher order functions provide more than just readability, are they more efficient?
- Can I make the nested
function skips()
better (readable/faster)? - Anything at all.
function skip(str, cb) {
var input = str.split('');
cb(input.map(skips));
function skips(val, index, arr) {
var res = [];
var i = index;
var iterator = i + 1;
for (i; i < arr.length; i += iterator){
res.push(arr[i]);
}
return res;
}
}
skip('hello!', console.log);
2 Answers 2
I agree with most of what @Dair said, but disagree with polluting the global namespace with a skipHelper()
that is of little value to anyone else.
I'd also make a few tweaks to the helper:
- It can be an anonymous function.
- I'd call the first parameter
_
to indicate that it is unused. var i
can be declared in thefor
loop header.extracted
would be a slightly more descriptive name thanres
.
function skips(str) {
return str.split('').map(function(_, index, array) {
var extracted = [];
for (var i = index; i < array.length; i += 1 + index) {
extracted.push(array[i]);
}
return extracted.join('');
});
}
-
\$\begingroup\$ Thank you for the response. A follow up questions on your answer. Is there a benefit of using an anonymous function? \$\endgroup\$boatSoap– boatSoap2015年09月08日 16:40:39 +00:00Commented Sep 8, 2015 at 16:40
Ok, first off: Passing in console.log
as a paramater seems unnecessary. The function should have one task:
Generate the skips
Then once you have the skips you can do whatever you want with it. So:
function skip(str, cb) -> function skip(str)
and:
skip('hello!', console.log); -> console.log(skip('hello'));
I would also not use a function within a function. I would try keeping the functions relatively small. Split the functions:
function skipHelper(val, index, arr) {
var res = [];
var i = index;
var iterator = i + 1;
for (i; i < arr.length; i += iterator){
res.push(arr[i]);
}
return res;
}
function skip(str) {
var input = str.split('')
return input.map(skips);
}
Also, given that str.split('')
isn't too much to explicitly write out, change:
var input = str.split('')
return input.map(skips);
To just:
return str.split('').map(skips);
Also, your code doesn't run exactly as described. Add a .join('')
to return res;
and this should fix it:
return res; -> return res.join('');
All in all:
function skipHelper(val, index, arr) {
var res = [];
var i = index;
var iterator = i + 1;
for (i; i < arr.length; i += iterator){
res.push(arr[i]);
}
return res.join('');
}
function skip(str) {
return str.split('').map(skipHelper);
}
console.log(skip('hello!'));
There are probably some Javascript language specific stylistic choices I am missing, but this is for general code structure.
-
\$\begingroup\$ Hello. Thank you for the response. Passing
console.log
is useless and it was used as a placeholder, your layout is much cleaner. I was attempting to model an async function. \$\endgroup\$boatSoap– boatSoap2015年09月08日 16:50:19 +00:00Commented Sep 8, 2015 at 16:50