Return required for Ternary Operator - javascript

why do we need to add 'return' to the ternary operator on line 4?
when I evaluate a standalone ternary operator such as 'five' === 'five' ? 1 : 0 I get a return value of 1. So my understanding is that a value was returned with that expression. So the 'return' on line 4 seems unnecessary although it is definitely needed for the code to run.
var countOccurrence = function(array, value) {
var n =array.length - 1;
if(n===0) {
return array[0] === value ? 1 : 0;
} else {
if(array[n] === value) {
return 1 + countOccurrence(array.slice(0,n), value)
} else {
return countOccurrence(array.slice(0,n), value)
}
}
};

Unlike input on the devtools console, JavaScript functions do not return the result value of the last statement to be evaluated. You need an explicit return keyword to terminate the function and return a result to the caller. If the function body evaluation ends without a return, the value undefined is returned implicitly.

Like the previous answers have stated, you need to explicitly return a result, otherwise the result of a function will be undefined. This can be done by using the return keyword, but since javascript ES6, the return keyword is no longer neccessary when using an arrow function expression.
The following function:
const fn = function(x, y) {
return x+y;
}
could be written in ES6 in the following way (without the need for the return keyword):
const fn = (x, y) => x+y;
With this in mind (and some functional programming principles), we could rewrite your function countOccurrence in the following way:
const countOccurrence = array => value => array.filter(y => y == value).length;
const array = [2,3,2,4,2];
const valueToCheck = 2;
console.log(countOccurrence(array)(valueToCheck)); // => 3

Related

freeCodeCamp Golf code but with Ternary operators instead of else if [duplicate]

I have a function to check sums in an array :
function checkSum(array, sum) {
// array = [1,4,6,11] sum = 10
var answers = [];
var map = new Map();
for (var x = 0; x < array.length; x++) {
if (map.has(array[x])) {
answers.push([sum - array[x], array[x]])
} else {
map.set(sum - array[x])
}
}
answers.length != 0 ? console.log(answers) : console.log("nada")
}
I originally had the last line just return answers; but let's say I don't want to return an empty array -- instead, I'd rather just log a statement.
why doesn't a return in a ternary conditional work such as this:
answers.length != 0 ? return answers : console.log("nada")
You need to use return answers.length != 0 ? answers : console.log("nada"). The reason it fails is because ternary conditions do not support return in their conditions. Infact, the ternary operator evaluates to an expression and expressions do not contain a return statement.
function checkSum(array, sum) {
// array = [1,4,6,11] sum = 10
var answers = [];
var map = new Map();
for (var x = 0; x < array.length; x++) {
if (map.has(array[x])) {
answers.push([sum - array[x], array[x]])
} else {
map.set(sum - array[x])
}
}
return answers.length != 0 ? answers : console.log("nada")
}
console.log(checkSum([1, 4, 6, 11], 10));
The ternary (conditional) operator expects the "expr1" part (where return answers is) to be an expression - that is, something that can be evaluated to a value, which can be used in other expressions. But a return statement is a statement, one which cannot possibly be interpreted as value, or as an expression; hence, a syntax error is thrown.
Instead of
answers.length != 0 ? console.log(answers) : console.log("nada")
either use a standard if statement:
if (answers.length !== 0) return answers;
console.log('nada');
or, if you just want to log, put the conditional operator inside the console.log instead:
console.log(
answers.length === 0
? 'nada'
: answers
)
I used ternary operators like this a lot in the past. It's fun, and keeps it to one line.
It can certainly be done, as Ankit shows, by putting the return statement out front
return answers.length != 0 ? answers : console.log('nada')
But I would recommend you use a classic if statement for this. Particularly since you're testing whether to return a value or just log one.
if (answers.length != 0) {
return answers;
};
console.log('nada')
I would go even further and recommend that you return the same value type no matter what. This will go a long way for using your function, well - functionally. In this case, that would involve still returning the array (even if it's empty) and logging the nada as well if empty.
if (answers.length == 0) {
console.log('nada');
};
return answers;

Not understanding the second return statement in this function

I am learning javascript and while I was on Codewars I couldn't figure this problem out so I looked for a solution.
This is the solution I found and I just don't understand why there needs to be a second return statement inside the map method. If anyone could give me some insight it would be much appreciated. Thank you.
let spinWords = (str) => {
return str.split(' ').map(function(string) {
return (string.length > 4) ? string.split('').reverse().join('') : string
}).join(' ');
}
The .map function accepts a callback, and that callback is a function that runs for every item in the array. For a simple example:
const upperCase = str => str.toUpperCase();
console.log(
['a', 'b'].map(upperCase)
);
Above, it's called with both elements of the array: upperCase('a') and upperCase('b'), and the results are put into the new array, which is then console.logged.
You can also define functions inline and pass that to .map:
console.log(
['a', 'b'].map(str => str.toUpperCase())
);
Your code's original
str.split(' ').map(function(string) {
return (string.length > 4) ? string.split('').reverse().join('') : string
}).join(' ');
is doing the same sort of thing, except that
the body of the function is more complicated, and
it's using the function keyword, rather than an arrow function, and thus needs the return keyword in order to return values (unlike arrow functions in some circumstances).
The second return is a callback function. Try looking at it like this:
function reverseWord(string) {
return (string.length > 4) ? string.split('').reverse().join('') : string
}
let spinWords = (str) => {
return str.split(' ').map(reverseWord).join(' ');
}
So reverseWord is your callback function, with its own return. The value it returns is the value used in the mapped array.

How to check if less than 2 of 3 variables are empty

I need to check that there are at least 2 values before running a script, but can't seem to get the condition to fire.
When I use if (risForm) {... the script runs when risForm is filled, and when I use if (!(risForm)) {... the script runs if risForm is empty, but I can't seem to work out how to check if any 2 of the three is full... I've tried this:
if ((!(risForm)) + (!(runForm)) + (!(angForm)) < 2) {...
along with a numerous adjustments to precise formatting/bracketting, but it's not getting me anywhere!
Make an array of the variables, filter by Boolean, then check the length of the array:
const forms = [risForm, runForm, angForm];
if (forms.filter(Boolean).length < 2) {
throw new Error('Not enough forms are filled');
}
// rest of the code
You can avoid creating an intermediate array by using reduce instead, if you wanted:
const filledFormCount = forms.reduce((a, form) => a + Boolean(form), 0);
if (filledFormCount < 2) {
throw new Error('Not enough forms are filled');
}
If you can have all your variables inside an array, you can do
yourArray.filter(Boolean).length >= 2
To break it apart, let's rewrite the above in a more verbose fashion:
yourArray
.filter(
function (variable) {
return Boolean(variable)
}
)
.length >= 2
Now, array.filter() gets every variable in the array and runs each as the argument for the function inside the parens, in this case: Boolean(). If the return value is truthy, the variable is "filtered in", if not it is "filtered out". It then returns a new array without the variables that were filtered out.
Boolean() is a function that will coerce your value into either true or false. If there's a value in the variable, it will return true... But there's a catch: it will return false for zeroes and empty strings - beware of that.
Finally, we use .length to count how many variables were "filtered in" and, if it's more than two, you can proceed with the code.
Maybe this pseudo code can illustrate it better:
const variables = ['foo', undefined, 'bar'];
variables.filter(Boolean).length >= 2;
['foo', undefined, 'bar'].filter(Boolean).length >= 2;
keepIfTruthy(['foo' is truthy, undefined is falsy, 'bar' is truthy]).length >= 2;
['foo', 'bar'].length >= 2;
2 >= 2;
true;
Javascript's true and false are useful here because when coerced to a number, they become respectively 1 and 0. So...
function foo(a,b,c) {
const has2of3 = !!a + !!b + !!c;
if ( has2of3 ) {
// Do something useful here
}
}
One caveat, though is that the empty string '' and 0 are falsy, which means they would be treated as not present. If that is an issue, you could do something like this:
function foo(a,b,c) {
const hasValue = x => x !== undefined && x !== null;
const has2of3 = hasValue(a) + hasValue(b) + hasValue(c);
if ( has2of3 ) {
// Do something useful here
}
}
let risForm = "a",
runForm = "",
angForm = "";
let arr = [risForm, runForm, angForm]
let res = arr.filter(el => !el || el.trim() === "").length <= 1
console.log(res)
There many ways to solve this. Lets try with basic idea. You want to make a reusable code and something that support multiple variables, also condition value might change. This means, we need to define an array of the form values and a condition value to verify. Then we can apply a function to verify the condition. So let's try some code:
let risForm, runForm, angForm;
risForm = 'Active';
// runForm = 3;
const formValues = [risForm, runForm, angForm];
const minFilledForms = 2;
const hasValue = a => !!a && a !== undefined && a !== null;
verifyForms();
function verifyForms() {
let filledForms = formValues.reduce((count, form) => count + hasValue(form), 0);
if (filledForms < minFilledForms) {
console.log(`Only ${filledForms} of ${formValues.length} forms have filled. Minimum ${minFilledForms} forms are requiered.`);
}
console.log('Continue...');
}

Javascript closure returning string instead of function

I am trying to write a simple compose function that takes a series of functions, and composes them like so:
compose(func1, func2, func3)(n) === func1(func2(func3(n)))
I do so by recursing through a rest parameter,
var compose = function(...args) {
return (n) => {
if (args.length) {
return args[0](compose(args.slice(1)));
} else {
return n;
}
};
};
I then attempt to compose a new function made up of a series of other functions,
var plusOneAndTwo = compose((n) => n + 1, (n) => n + 2);
plusOneAndTwo(1);
Instead of returning 4, I get back the body of the inner, anonymous function inside of compose as a string,
"(n) => {
if (args.length) {
return args[0](compose(args.slice(1)));
} else {
return n;
}
}1"
Note the "1" at the end of the string! I have no idea why this is happening, and in particular I'm perplexed by how a 1 is getting appended to the end of that.
Any clarification is appreciated, thanks!
The problem occurs in the recursive call to compose.
In particular, you are not passing the parameter n to it (as also suggested by others above). Furthermore, you need to expand the rest parameter in the call.
You should use something like:
return args[0](compose(...args.slice(1))(n))
In your case, you are simply returning:
return args[0](compose(args.slice(1)));
In your example you call compose((n) => n + 1, (n) => n + 2);. Compose then returns a function taking n as a parameter. In this function, args.length becomes 1 (i.e. true-is), args[0] becomes (n) => n + 1 and args.slice(1) becomes [(n) => n + 2].
Next, you call this returned function with the parameter n = 1. As args.length is 1, the if() statement will go into the if() case. In this if case, it will call args[0] with the argument compose(args.slice(1)).
In this recursive call, compose(args.slice(1)) is evaluated to a function, taking n as a parameter and the same function body.
This function is then given as the parameter n to args[0] (in the outer call). Recall that args[0] in this scenario is the function (n) => n + 1.
Thus the call as a whole is equivalent to:
// returned from the recursive call to compose(args.slice(1))
var n = (n) => {
if (args.length) {
return args[0](compose(args.slice(1)));
} else {
return n;
}
}
// applied to arg[0] == (n) => n + 1
return n + 1
This means that the code will attempt to add a function with the number 1.
In JavaScript adding a function and a number results in both objects coerced into a string. Casting a number into a string is trivial, casting a function into a string returns the function source code. These strings are then added to give the return value you saw: The function body as a string with the 1 at the end.
You just have to call the composed function:
return args[0](compose(...args.slice(1))(n));
Or without recursion it'll be:
const compose = (...fns) => start => fns.reduceRight((acc, fn) => fn(acc), start);
You could take a different approach by returning a new function or returning the last function for calling with arguments.
const
compose = (...fns) => fns.length
? v => compose(...fns.slice(0, -1))(fns.pop()(v))
: v => v,
fn1 = n => n * 5,
fn2 = n => n + 2,
fn3 = n => n * 7;
console.log(fn1(fn2(fn3(1))));
console.log(compose(fn1, fn2, fn3)(1));

Extending the logical OR || syntax for the empty array

Let f and g be two function. Then f() || g() first evaluates f. If the return value of f is falsy it then evaluates g, and returns g's return value.
I love the neat and concise syntax, but it doesn't include the case where f returns the empty array [], which I want to consider "falsy".
Is there clean way of having this syntax for [] instead of the traditional falsy values?
You could write a function that converts the empty array into a real falsy value, maybe?
function e(a) { return a instanceof Array ? (a.length ? a : false) : a; }
var result = e(f()) || g();
The problem with the other solutions presented is that it doesn't behave exactly how you may want the short-circuiting to work. For example, converting the value of f() to a truthy value before the || operator means you lose the ability of returning the result of f(). So here's my preferred solution: write a function that behaves like the || operator.
// let's call the function "either" so that we can read it as "either f or g"
function either () {
var item;
// return the first non-empty truthy value or continue:
for (var i=0;i<arguments.length;i++) {
item = arguments[i];
if (item.length === 0 || !item) continue
return item;
}
return false;
}
We can now use the either() function like how we would the || operator:
either(f(), g());
Why not simply do the length check at f()?
function f(){
var returned_array = new Array();
...
if(!returned_array.length)
return false;
}
If you're talking about actually overloading the || operator, you cannot do that in JavaScript (it was proposed back in ECMAScript 4 but rejected). If you really want to do operator overloading in JavaScript, you'd have to use something like JavaScript Shaper, which is "an extensible framework for JavaScript syntax tree shaping" - you could actually use this to overload operators.

Categories

Resources