In the following recursive function, I expect the function to return "arrived" at the end but instead, it returns undefined. Isn't that when the excution goes in the if block the code should return? Appreciate your comments on this.
function myFun(i){
if(i===0){return ('arrived');}
i = i - 1;
myFun(i);
}
If I change the code as follows then it'll return "arrived" but still don't know why the above doesn't return "arrived".
function myFun(i){
if(i===0){return ('arrived');}
i = i - 1;
return myFun(i);
}
The first function does not return a value because all code paths must return a value. And after the first line, there is no return statement. It only returns a value when called with 0 as parameter.
Recursion is a functional heritage and so writing your program in a functional style will yield the best results.
This means avoiding things like
imperative style statements for, if, switch, etc that do not return a value
mutation or variable reassignments like i = i + 1
const myFun = i =>
i === 0
? "arrived"
: myFun (i - 1)
console.log (myFun (10))
// "arrived"
Notice expressions, unlike statements, evaluate to a value. We made the following changes
function statement function myFun (i) { ... } replaced with a function expression myFun (i) => ...
if statement replaced with ternary expression, eg condition ? ifTrue : ifFalse
variable assignment statement i = i - 1; myFun(i) replaced with expression myFun(i - 1)
Note, the return statement itself is a side effect and has little use in a functional JavaScript program.
Going along with the other answer here, all code paths must return a value! An advantage to writing your program in a functional style means you can't write a function that doesn't return a value, nor can you write a conditional with only one branch.
TL;DR: use functional style and your problem automatically vanishes
Related
I am new to Javascript and sort of working through the weeds on these ternary operators. I have this small code segment:
const x = MSys.inShip ? 'ship launch' : '';
if (x != '') {send_command(x);}
While this works efficiently enough I am curious as to if it can be rewritten inside of the function call. Something like the following:
send_command(const x = MSys.inShip
? 'ship launch'
: MSys.alert("You aren't in your ship!);
This may not make sense with the current example but it's the best idea I had at the time. Basically, I like the shorthand of the ternary style for easy if/then conditionals but I don't like how it's tied to a variable which must then be called. I'm looking for a way to use that shorthand without having to tie to a variable.
Finally, the purpose of this is to see if you are in the ship and if you are, launch. If you aren't don't do anything at all or just send an alert message.
I am curious as to if it can be rewritten inside of the function call.
Yes, it can. But, if you do it there, then there is no need for a variable. You would be passing the function's argument directly inline.
Having said that, you can't pass that MSys.alert() statement as the "else" value because it will be executed in all cases. You'd have to pass a value there that the function can use as its input argument
send_command(MSys.inShip ? 'ship launch' : 'some other string');
Here's an example:
function foo(x){
console.log(x);
}
// If a random number is even, pass "even". If not, pass "odd"
foo(Math.floor(Math.random() * 10) % 2 === 0 ? "even" : "odd");
An important distinction between your two approaches - The second approach will ALWAYS call send_command() whereas your first approach will conditionally call it.
This distinction will matter depending on your implementation of send_command, but it sounds like you want the behavior of the first approach.
Additionally, You can't declare variables using const in a function call. If you just pass in the ternary operator, you will end up calling send_command with either your string, or undefined (the return of calling alert() ).
However, as an answer to your question, yes you can pass the ternary operator to a function like any other value. The ternary operator is an expression that will return a value.
Technically, you could keep a variable (such as operation) below, which references which method you want to execute, depending upon some conditional. And then you could pass that variable method the variable string it should get.
So, as you can see, it can be done. But look at how much complication was added to the process, rather than just using a simple if else statement.
function test_logic ( inShip ) {
// if they are in their ship, the operation should be the send_command method
// otherwise it should be the window alert
var operation = inShip ? send_command : window.alert;
function send_command ( command ) {
console.log( command );
}
// give the operation the desired string
operation( inShip ? 'ship launch' : "You aren't in your ship!" );
}
console.log( "Not in ship test" );
test_logic( false );
console.log( "In ship test" );
test_logic( true );
My code (which works):
const calculateBalance = (coins) => {
console.log('coins', coins);
return coins.reduce((bal, coin) => (bal += parseInt(coin.balance)), 0);
};
Basically I just want to add up all the coin balances in my portfolio, however I'm getting an eslint error.
Arrow function should not return assignment.
Googling I found this: https://eslint.org/docs/rules/no-return-assign
One of the interesting, and sometimes confusing, aspects of JavaScript is that assignment can happen at almost any point. Because of this, an errant equals sign can end up causing assignment when the true intent was to do a comparison. This is especially true when using a return statement.
Here they have an example of what to do:
function doSomething() {
return (foo = bar + 2);
}
However that is what I implemented, but eslint is still complaining... is there a way to update my code block above to make it pass?
From the specs. (here MDN)
The reduce() method applies a function against an accumulator and each
element in the array (from left to right) to reduce it to a single
value.
As your bal is your accumulator, simply do bal + parseInt(coin.balance)
What is the difference between a statement and a expression? How can i know each one is?
Why void transform this:
void function() {
}();
into an expression?
And why this works:
something((something) => something + 2);
and this don't:
something((something) => if (something) { something + 2 });
?
Thanks!!
Statements and expressions are different language units. What's probably tripping you up is that JavaScript, unlike some other languages, has what the spec calls ExpressionStatement: It can treat any expression as a statement (but it cannot treat statements as expressions). So for instance, this is valid JavaScript:
flag && console.log("Hi there");
...whereas in (say) Java that wouldn't be valid, because while Java has some specific statements to allow for specific expression-like things (method calls, for instance), it doesn't have JavaScript's overall ExpressionStatement.
Why void transform this:
void function() {
}();
into an expression?
Because void is an operator. It evaluates its operand (whatever follows it), and then sets its result to undefined. It's not at all related to the void that you see in languages like C, C++, Java, or C#. So the whole thing is an ExpressionStatement. The only reason you need the void there is that without it, when the parser is expecting to see a statement, the keyword function puts the parser into a state where it's expecting a function declaration, not an expression. (You can use any operator, not just void, to put the parser into expression state; details in this question and its answers.)
And why this works:
something((something) => something + 2);
and this don't:
something((something) => if (something) { something + 2 });
Because of the way arrow functions are defined by the specification. There are two forms of arrow function:
Ones with a concise body (no {})
Ones with a verbose body
Concise example:
array.sort((a, b) => a - b);
Equivalent verbose example:
array.sort((a, b) => {
return a - b;
});
Arrow functions with concise bodies require that the body be an expression because, as you can see above, they return the result of the expression. You can't use a statement there for the same reason you can't use a statement other places an expression is required: A result value is needed for the implicit return statement. Your second example, translated to a verbose body, is this:
something((something) => {
return if (something) { something + 2 };
});
...which demonstrates why it didn't work: You have an if after return, but the return statement requires an operand (expression) or statement terminator instead.
In short, expression refers to value, statement defines behavior.
For a complete explanation you should always read the top voted answer: T.J. Crowder's answer
Let me just show you some naive examples.
The following code define a value. It is a statement called let statement led by let keyword. Here 1 is an expression.
// statement
// |---------|
let n = 1 ;
// |-|
// expression
And this is for statement led by for keyword. It comes with some nested expressions and statements.
// expression(1)
// |-----------|
for (num in numArr) { //--+
// |
sum += (num * 3); // statement(2) // |
// |-----| // |statement(1)
// expression(2) // |
// |
} //--+
So a statement is an instruction unit telling computer what to DO. for statement, while statement, if statement, they are all Actions, in another word Tasks.
But for expression, we are talking about values, valuables, objects, or some procedures that can produce a value, like function.
1 + 2
(2 + 3) * 5 === 25
new Foo()
So Javascript also has function expression. Because function is a value. In the following code,
The entire snippet is a statement.
Everything after = is an expression.
return width * height; is nested statement.
width * height is an expression.
const rectArea = function(width, height) {
return width * height;
};
I have a syntax question, lets say i have the following function. It received text for spell check and returns the correct text or false in case the text was already spelled correctly.
var spellCheck = function (txt) {
var spelledTxt = spell(txt);
if (spelledTxt =! txt) { //the text had a typo.
return spelledTxt;
}
return false;
}
Now in a different function i want to call this function from an ElseIf statement, and i want to get into that statement only if the text had a typo which was corrected. something like:
if(something){
do something....
}else if(spellCheck(word)){
do something with the spelledTxt that was returned from "spellcheck"
}
Can i just do:
else if(var spelledWord = spellCheck(word))
do something with spelledWord.
I forgot a very important thing: spellCheck(word) is very heavy function and i'd like to avoid calling it if not needed. This mean that only if we arrived to the else if() it will be called, and not sooner.
Any expression is valid inside an if statement, and that includes an assignment expression. The value of an assignment expression is the assigned value.
In your case the return value of the function call is the value of the expression, but the var makes it a statement and not a simple expression.
You need to remove the variable declaration part from the statement and then it's fine.
Alternatively, you could simply do it like this:
else {
var spelledWord = spellCheck(word);
if(spelledWord)
do something with spelledWord
}
You can do that. The assignment operation returns a value, which you could use as a boolean expression.
But you should remember that:
In Javascript var statement is function-scoped.
There is a 'hoist' behavior in Javascript.
As a result of 1,2 and some later code refactoring, you could easily introduce a bug to this code.
Type coercion in Javascript is a bit messy.
Reading code with side effects, where one operation could lead to 2 different logic outcomes simultaneously - is really hard work.
I'd consider using the strict comparison operators at least: if (spelledWord = spellCheck(word) !== '')
And if it's possible, try to memoize (cache) results from calling spellCheck function. In that case, you wouldn't need to combine two operations into one at all.
Are the two identical?
Suppose you have:
var x = true;
And then you have one of either:
x && doSomething();
or
if(x) doSomething();
Is there any differene whatsoever between the two syntaxes? Did I stumble across a nice bit of sugar?
Strictly speaking, they will produce the same results, but if you use the former case as a condition for something else, you will get dissimilar results. This is because in the case of x && doSomething(), doSomething() will return a value to signify its success.
No, they are not identical. While if is a statement, the AND operator is an expression.
That means you could use its result in an other expression, which you can't with an if-statement:
var result = x && doSomething();
Yet, in your case both have the same effect. Use the one that is more readable and represents your program structure better; I'd recommend the if-statement.
Short answer: No.
Long answer:
A stated by #Steve x && doSomething() is an expression,
whereas if(x) doSomething(); is a statement,
As suggested by #Daniel Li and #Bergi, think:
an expression is computed ( supposed to return a value here ).
a statement is declared ( not supposed to return a value here, think side-effects ).
Why is it confusing?
JS allows us to write ( thatExpression );
JS allows us to write thatExpression;
both assuming some kind of doNothingWithValueOf statement.
How to choose?
Do you use:
doSomething() as an
expression , think IsMyObjectWhatever() or MyObjectComputedValue(),
or as a statement, think ModifyMyObject()
And then: Do you use x && doSomething() as an expression ?
You'll end up thinking something like thisStatement( thatExpression ); everywhere, think:
() expression,
; statement.
Then why should I choose?
Obvious is that "It works." doesn´t stand for "It´s right".
If less obvious is when it will make the difference:
just think ()(()())()(); can be right, (;) is wrong.
check #wwaawaw Javascript: difference between a statement and an expression?
or expressions-vs-statements post by Axel Rauschmayer
In a word no, the two statements are not equal, though in the specific circumstances you present the outcome is the same.
x && doSomething(); is an expression, first the x evaluated, because this is an AND and since x is true the second argument (doSomething()) is then evaluated. In this case this means that the method is executed. If x were false then doSomething() would not be executed as the result of the expression cannot be true.
if(x) doSomething(); is a statement. The value of x is checked, and if it is true the scope of the if statement is executed.
I've put together this fiddle to demonstrate (with minor modifications).
Let's play detective.
We'll call our first approach Conditional Arrow Invocation and our second approach Traditional If Else.
We'll create two separate cases in jsperf to evaluate how these two approaches fair.
Conditional Arrow Invocations
const VALUE = true;
const TEST = false;
//test 1
VALUE && !TEST && (() => {
console.log('print me!');
})();
Ops/sec result:
FireFox: 65,152
Chrome: 129,045
Traditional If Else
const VALUE = true;
const TEST = false;
//test 2
if(VALUE && !TEST) {
console.log('print me!');
}
Ops/sec result:
FireFox: 65,967
Chrome: 130,499
Conclusion
As you can see, performance wise there isn't a huge difference but marginally Traditional If Else won over Conditional Arrow Invocation most of the times by an insignificantly small number. This might have something to do with creating an implicit function on the fly.
I also realized Chrome's JavaScript is a lot faster than FireFox's JavaScript execution.
Here is the jsperf link that you can run to evaluate this for yourself.
https://jsperf.com/conditional-methods-vs-traditional-if-else/1