Inline if with else - ruby

I realize that it's not valid ruby but what would be the technical hurdles to implement the below functionality into the Ruby core language (of say v2.3)?
variable = 1 if condition else -1
I'd also like to allow the following for more generic use.
variable = { 1 } if condition else { -1 }
I'm very open to requiring an "end" at the end.
I get that a ternary can easily accomplish this but I'm looking for a more readable inline-if that allows an else.
I get that I can make a function which does this via any number of styles but I'd prefer to have it as readable as possible.
Thanks.
EDIT: I hate editing questions for obvious reasons.
In response to the question of how the generic option is more ruby-esque, see the below example (I needed newlines).
variable = {
operation_one
operation_two
...
SUCCESS_STATUS_CODE
} if loaded_dependencies else {
do_detailed_logging
FAILURE_STATUS_CODE
}
if variable then
it_worked
else
explain_why
end

Because your example, while it seems readable to you, has too many ambiguities in other cases.
Not to mention that ruby has a way to do this, and it's the ternary operator. To say that your example is more ruby-like, is almost like wondering why the wheelbase of the Ford Mustang wasn't longer, and that it would be more "Mustang-like" if it was.
But here are some issues with your proposal, starting from your example:
variable = { 1 } if condition else { -1 }
Here you've given your "if else" bit a lower precedence than the "=".
In other words:
variable = ({ 1 } if condition else { -1 })
That's a serious problem, because it breaks the currently allowed:
variable = 1 if condition
The precedence for that statement is:
(variable = 1) if condition
And that's important. No assignment happens if the condition is false.
This can be a really big deal, for example if the lvalue (left side) actually has side-effects. For example:
var[0] = 1 if condition
The lookup for "var[0]" is a method in whatever class object var is, and while [] doesn't usually have side-effects, it can - and now you are going to do those side effects even if the condition is false.
And I won't even get into:
variable = { 1 } if condition if condition2 else { -1 }
But if you don't like it, you can always write your own language and see what happens!

Related

golang's fallthrough seems unexpected

I have the following code:
package main
import (
"fmt"
)
func main() {
switch {
case 1 == 1:
fmt.Println("1 == 1")
fallthrough
case 2 == 1:
fmt.Println("2 == 1")
}
}
Which prints both lines on the go playground - see example here. I would have expected the fallthrough statement to include evaluation of the next case statement, but this seems not to be the case.
Of course, I can always use a bunch of if statements, so this is not a real impediment, but I am curious what the intention here is, since this seems to me to be a non-obvious result.
Anyone care to explain? For example: in this code, how can I get the 1st and 3rd cases to execute?
Switch is not a bunch of ifs. It's more akin to if {} else if {} construct, but with a couple of twists - namely break and fallthrough. It's not possible to make switch execute first and third cases - a switch does not check each condition, it finds first match and executes it. That's all.
It's primary purpose is to walk through a list of possible values and execute a different code for each value. In fact, in C (where switch statement came from) switch expression can only be of integral type and case values can only be constants that switch expression will be compared too. It's only relatively recently, languages started adding support for strings, boolean expressions etc in switch cases.
As to fallthrough logic it also comes from C. There is no fallthrough operator in C. In C execution falls through into next case (without checking case values) unless break operator encountered. The reason for this design is that sometimes you need to do something special and then do same steps as in another case. So, this design merely allows that. Unfortunately, it's rather rarely useful, so falling through by default was causing more trouble when programmer forgotten to put a break statement in, then actually helping when truly omitted that break intentionally. So, many modern languages change this logic to never fall through by default and to require explicit fallthrough statement if falling through is actually required.
Unfortunately, it's a it hard to come up with a non contrived example of fallthrough being useful that would be short enough to fit into an answer. As I said it's relatively rare. But sometimes you need to write code similar to this:
if x == a || x == b {
if x == a {
// do action a
}
// do action ab
} else if x == c {
// do action c
} else if x == d {
// do action d
}
In fact, I needed code of similar structure quite recently in one of my projects. So, I used switch statement instead. And it looked like this:
switch x {
case a: // do action a
fallthrough
case b: // do action ab
case c: // do action c
case d: // do action d
}
And your switch from the question is functionally equivalent to this:
if 1 == 1 || 2 == 1 {
if 1 == 1 {
fmt.Println("1 == 1")
}
fmt.Println("2 == 1")
}
Presumably, Go's fallthrough behavior is modeled after C, which always worked like this. In C, switch statements are just shorthands for chains of conditional gotos, so your particular example would be compiled as if it was written like:
# Pseudocode
if 1 == 1 goto alpha
if 2 == 1 goto beta
alpha:
fmt.Println("1 == 1")
beta:
fmt.Println("2 == 1")
As you can see, once execution enters the alpha case, it would just keep flowing down, ignoring the beta label (since labels by themselves don't really do anything). The conditional checks have already happened and won't happen again.
Hence, the non-intuitive nature of fallthrough switch statements is simply because switch statements are thinly veiled goto statements.
From the language spec:
A "fallthrough" statement transfers control to the first statement of the next case clause in an expression "switch" statement. It may be used only as the final non-empty statement in such a clause.
That seems to perfectly describe your observed behavior.

Difference between if as an expression and if as a statement

So I was watching this video on the Go language - https://www.youtube.com/watch?v=p9VUCp98ay4 , and at around 6:50 a guy asks a question about why they implemented if's as statements and not expressions. What is the difference between those two implementations? As far as I know, I've never had to change the way I use a conditional based on the language.
Edit: and what does he mean that "you need values rather than variables" in his question?
The difference between expressions and statements is that expressions produce a value and thus can be used in places where values are required. So expressions can be used as values for variables, arguments to functions or operands to operators. Statements can't.
and what does he mean that "you need values rather than variables" in his question?
I assume that by vals he means constants (which are called vals in Scala for example).
If if were an expression, you could do this:
const myValue = if condition { value1 } else { value2 }
Since if is not an expression, you have to do this:
var myValue
if condition {
myValue = value1
} else {
myValue = value2
}
So you needed to make your variable mutable (use var instead of const), which is what the person asking the question likely meant.
You can get the same code elegance that you would get from if expression by using an instantly invoked function (IIF) combined with if statements in GO. I'm not a GO programmer (mainly typescript) so please let me know if this is bad for performance for any reason.
func main() {
amIHungry := true
didMyPaycheckComeInYet := false
choice := func() string {
if(!amIHungry && !didMyPaycheckComeInYet){
return "stay-home"
}
if(!amIHungry && didMyPaycheckComeInYet){
return "buy-new-keyboard"
}
if(amIHungry && !didMyPaycheckComeInYet){
return "make-ramen"
}
return "taco-bell-time"
}()
println(choice)
}
and then later on in your program, rather than having a bunch of out of context states, you can have a simplified "choice" to choose your app logic.
if(choice == "taco-bell-time"){
println("Order a bean burrito, but with black beans,")
}
is a little easier to reason about than
if(amIHungry && didMyPaycheckComeInYet){
println("Order a bean burrito, but with black beans,")
}

If/ Else, test true first or false first

I have a rather specific question.
Say I am at the end of a function, and am determining whether to return true or false.
I would like to do this using an if/else statement, and have two options: (examples are in pseudocode)
1) Check if worked first:
if(resultVar != error){
return true;
}else{
return false;
}
2) Check if it failed first:
if(resultVar == error){
return false;
}else{
return true;
}
My question is simple: Which case is better (faster? cleaner?)?
I am really looking at the if/else itself, disregarding that the example is returning (but thanks for the answers)
The function is more likely to want to return true than false.
I realize that these two cases do the exact same thing, but are just 'reversed' in the order of which they do things. I would like to know if either one has any advantage over the other, whether one is ever so slightly faster, or follows a convention more closely, etc.
I also realize that this is extremely nitpicky, I just didn't know if there is any difference, and which would be best (if it matters).
Clarifications:
A comparison needs to be done to return a boolean. The fact that of what the examples are returning is less relevant than how the comparison happens.
This is by far the cleanest:
return resultvar != error;
The only difference in both examples may be the implementation of the operator. A != operator inverses the operation result. So it adds an overhead, but very small one. The == is a straight comparison.
But depending on what you plan to do on the If/else, if there is simply assigning a value to a variable, then the conditional ternary operator (?) is faster. For complex multi value decisions, a switch/case is more flexible, but slower.
This will be faster in your case:
return (resultVar == error) ? false : true;
This will depend entirely on the language and the compiler. There is no specific answer. In C for instance, both of these would be encoded rather like:
return (resultVar!=error);
by any decent compiler.
Put true first, because it potentially eleiminates a JUMP command in assembly. However, the difference is negligible, since it's an else, rather than an else if. There may /technically be a difference/, but you will see no performance difference in this case.

Go code doesn't compile without an unreachable return statement

Here is the program to find the factorial of a number in Go:
func factorial(x uint) uint {
if x == 0 {
return 1
}
return x * (factorial(x - 1))
}
The output for this function when called on input 5 is 120. However, if I add an else statement I get an error.
func factorial(x uint) uint {
if x == 0 {
return 1
} else {
return x * (factorial(x - 1))
}
}
Error : function ends without a return statement
I added a return at the end :
func factorial(x uint) uint {
if x == 0 {
return 1
} else {
return x * (factorial(x - 1))
}
fmt.Println("this never executes")
return 1
}
and I get back the expected output of 120.
Why would the second case cause an error? Why in the third case even though the function never reaches the last return 1, it computes the correct output?
This is a well known problem of the compiler.
There is even an issue logged : http://code.google.com/p/go/issues/detail?id=65
In the words of one of the authors of the Go language:
The compilers require either a return or a panic to be lexically last
in a function with a result. This rule is easier than requiring full
flow control analysis to determine whether a function reaches the end
without returning (which is very hard in general), and simpler than
rules to enumerate easy cases such as this one. Also, being purely
lexical, the error cannot arise spontaneously due to changes in values
such as constants used in control structures inside the function.
-rob
From another comment in golang-nuts, we can infer it's not going to be "fixed" soon :
It's not a bug, it's a deliberate design decision.
-rob
Note that other languages like Java have rules allowing this else.
March 2013 EDIT - It just got changed in Go1.1 :
Before Go 1.1, a function that returned a value needed an explicit
"return" or call to panic at the end of the function; this was a
simple way to make the programmer be explicit about the meaning of the
function. But there are many cases where a final "return" is clearly
unnecessary, such as a function with only an infinite "for" loop.
In Go 1.1, the rule about final "return" statements is more
permissive. It introduces the concept of a terminating statement, a
statement that is guaranteed to be the last one a function executes.
Examples include "for" loops with no condition and "if-else"
statements in which each half ends in a "return". If the final
statement of a function can be shown syntactically to be a terminating
statement, no final "return" statement is needed.
Note that the rule is purely syntactic: it pays no attention to the
values in the code and therefore requires no complex analysis.
Updating: The change is backward-compatible, but existing code with
superfluous "return" statements and calls to panic may be simplified
manually. Such code can be identified by go vet.
And the issue I mentioned is now closed with status "Fixed".

Coding styles in conditional expression of some programming languages

It's a bit confusing to me about what is the difference between these condition expressions below:
if( 1 == a) {
//something
}
and
if( a == 1 ) {
//something
}
I saw the above one in some scripts I have downloaded and I wonder what's the difference between them.
The former has been coined a Yoda Condition.
Using if(constant == variable) instead of if(variable == constant), like if(1 == a). Because it's like saying "if blue is the sky" or "if tall is the man".
The constant == variable syntax is often used to avoid mistyping == as =. It is, of course, often used without understanding also when you have constant == function_call_retuning_nothing_modifiable.
Other than that there's no difference, unless you have some weird operator override.
Many programming languages allow assignments like a = 1 to be used as expressions, making the following code syntactically valid (given that integers can be used in conditionals, such as in C or many scripting languages):
if (a = 1) {
// something
}
This is rarely desired, and can lead to unexpected behavior. If 1 == a is used, then this mistake cannot occur because 1 = a is not valid.
Well, I am not sure about the trick. Generally, we could say the equal sign is commutative. So, a = b implies b = a. However, when you have == or === this doesn't work in certain cases, for example when on the right side you have a range: 5 === (1..10) vs. (1..10) === 5.

Resources