Shorthand for x ? x : y - ruby

Is there a shorthand for x ? x : y? A relatively tame example:
def find_or_create_by_name(name)
self.find_by_name(name) ? self.find_by_name(name) : self.create(name)
end
Of course I could do something like
def find_or_create_by_name(name)
x = self.find_by_name(name)
x ? x : self.create(name)
end
but then I'm starting to lose the space I've saved with the ternary operator in the first place. (and if I use a full if statement, the same redundancy would occur.

you can just use || operator:
def find_or_create_by_name(name)
find_by_name(name) || create(name)
end

Related

In Ruby, why doesn't ternary operator work when using a puts function inside an each statement?

Given that you write the code on IRB:
array = [1,2,3]
array.each {|x| x > 2 ? puts "lower" : puts "higher"}
The program doesn't execute the line and it somehow according to the program is an incomplete line. Any help would be appreciated.
This is caused by ambiguous arguments. Ruby, unlike many other languages such as JavaScript, is really lax about requiring brackets puts x and puts(x) are equivalent. Where this breaks down is when it's not clear which are arguments, and which are part of other syntax.
For example, if f is a method that takes 1-3 arguments and x and y are variables, then what is the meaning of:
f x, f x, y
Is that f(x, f(x,y)), f(x), f(x), y or f(x, f(x), y)? Ruby throws an error rather than presume the wrong thing.
Easy fix is to eliminate the duplication of effort here and use a single puts with a ternary used to determine the value:
array = [1,2,3]
array.each { |x| puts x > 2 ? "lower" : "higher"}
Now it works because there's no ambiguity on arguments, there's only one method call so it's easy.
The previous answer explains clearly what is happening. However you may note that this syntax will also work, but here you are duplicating the method call on both sides of the ternary operator:
array.each {|x| x > 2 ? (puts "lower") : (puts "higher")}
By wrapping the duplicate method call on both sides, that code is executed on both sides. But it definitely is better style to do it the more correct way where you are passing the result of ternary to puts
array.each { |x| puts x > 2 ? "lower" : "higher"}
which is the same as:
array.each { |x| puts (x > 2 ? "lower" : "higher") }
The puts method takes a single string argument and that's what we are passing it.

How to write a conditional lambda in Ruby?

I'd like to write a conditional lambda in Ruby. The Python equivalent of what I'd like to write is:
even = (lambda x: x if x % 2 == 0 else 0)
My attempt to write this in Ruby looks like:
even = -> (x) {x if x % 2 == 0 else 0}
Unfortunately, that does not work. Is there any way to fix this?
You have several options here to express this. The long-form is this:
if (x % 2 == 0)
x
else
0
end
Note that a trailing if or unless cannot have a secondary condition like else. You need to use the full form.
If you want a short version, you use the ternary operator:
(x % 2 == 0) ? x : 0
What you could also do is this:
(x % 2 == 0) and x or 0
As others have observed there's a method called even? which does the modulo for you, so that can collapse this further:
x.even? ? x : 0
Ruby's ternary operator has this syntax
x % 2 == 0 ? x : 0
You don't even need a conditional.
p = ->(x) { x*(1-x%2) }
p.call(4) #=> 4
p.call(5) #=> 0
Note procs can be called in multiple ways:
p[4] #=> 4
p.(4) #=> 4
p.yield(4) #=> 4
p === 4 #=> 4
p(4) #=> 4
The last of these may be archaic.
Wrong syntax. You can write it like this:
even = -> (x) {if x % 2 == 0; x; else; 0; end}
However, for such one-liners, it is more common to use the ternary ?: operator, as other have suggested in this thread.
Your syntax is wrong:
The then-block comes after the condition, not before it.
The then-block is separated from the condition by the then keyword, a semicolon, or a newline.
The conditional expression is terminated with an end keyword.
So, any of the following is valid:
# idiomatic:
if x % 2 == 0 then x else 0 end
# idiomatic:
if x % 2 == 0
x
else
0
end
# non-idiomatic:
if x % 2 == 0; x else 0 end
# non-idiomatic:
if x % 2 == 0 then
x
else
0
end
# non-idiomatic:
if x % 2 == 0
x else 0 end
# … and many other non-idiomatic variations
Ruby also has a conditional operator:
x % 2 ? x : 0
But I personally find it ugly and unreadable. It also has different precedence than the conditional expression, which may be surprising to some. (Witness the myriad of variations of the same question about the conditional operator here on StackOverflow.) And it is completely unnecessary: in C, where if is a conditional statement, the conditional operator is required because it is an expression. In Ruby, everything is an expression anyway, there are no statements, so of course if is an expression, too.

Is there an "&& Equals" operator in Ruby

I often find myself doing things like this:
do_something if x && x == y
In other works, do something if x is not nil, and it has a value of y.
It would be nice if I could do something like this instead:
do_something if x &&== y
Is there an operator that does this?
Responses to comments:
x == y - The problem with this, is that it only tests existence (not nil) if the value of y is known. If y is itself nil then the check fails. So you could end up doing:
y && x == y
x ||= y - This would assign the value of y to x if x is nil. That's not what I'm looking for. x &&= y doesn't work either for the same reason - it changes the value of x to y if x exists.
An example: in my current scenario I want to check that a user has passed to a controller the token associated with them, but I also want to ensure that the token has been assigned. Something like:
do_something if user.token && user.token == params[:token]
If you are using ruby > 2.3.0 you can use the &. operator: x&.== y. It basically does what .try does in Rails if the value of the operand is different than nil it calls the method and returns its result. If the value is nil it returns nil so you can do things like: do_i_exist&.does_the_result_exist&.nil?
See: What does &. (ampersand dot) mean in Ruby?

adequate solution to hand over variables in nested functions (in ruby)

I have several step_1-methods which are based on x and y variables.
step_2 creates new methods based on step_1-methods but the variables aren't needed (just passed through)!
The same goes for step_3 (based on step_2-methods).
My problem is I have about 20 step_2-methods which consists dozens of step_1-methods (5 differents kinds). And for each one I have to pass the same two variables.
I need this kind of construction for iteration purposes.
Now, is there a way to hand over the variables directly form step_3(x, y) to step_1 (x, y) without using global variables?
# example
def step_1 (x, y)
return x + y
end
def step_2 (*foo)
return step_1(*foo)
end
def step_3 (*foo)
return step_2(*foo)
end
x, y = 2, 2 # example
puts step_3(x, y) # ==> 4
Thanks for any suggestion
When I read "I have to pass the same two variables", this naturally brings to mind the idea of creating a simple container you can pass around instead:
class NumberTuple
attr_accessor :x
attr_accessor :y
def initialize(x, y)
#x = x
#y = y
end
end
tuple = NumberTuple.new(2,2)
step_3(tuple)
This often leads to the conclusion that creating a simple calculation class that can internalize all of this state. That's what class instances excel at:
class NumberCalculator
def initialize(x, y)
#x = x
#y = y
end
def step_3
step_2
end
def step_2
step_1
end
def step_1
#x + #y
end
end
calculator = NumberCalculator.new(2,2)
calculator.step_3
alias step_3 :step_1
or if you want to go through intermediate steps,
alias step_2 :step_1
alias step_3 :step_2

"Ruby-esque" if else conditional statements

I'm currently reading The Ruby Programming Language, and I am not sure how to read Ruby-esque if else statements properly. Can you help me write the ruby code below in the second code block in regular if-else statements like this?
if some_condition
return x
else
return y
end
So the ruby codes I am unsure of are these.
minimum = if x < y then x else y end
max = x > y ? x : y
Thank you!
Both of the forms you seem to be having difficulty with make use of an idea Ruby takes from the Functional Programming paradigm: namely, Everything is an expression, and therefore returns a value. This is even true for conditional statements, an idea that languages like Java don't really support (for example:
public boolean test() {
boolean x = if (1 > 2 ) { false; } else { true; };
return x;
}
simply isn't syntactically valid).
You can see this in a Ruby terminal:
will_be_assigned_nil = false if (1 > 2) # => nil
will_be_assigned_nil # => nil
So, to your question.
The first one can be rewritten like this:
if x < y
mininum = x
else
minimum = y
end
The second is like the ternary operator in other languages, and is equivalent to:
if x > y
max = x
else
max = y
end
It's helpful to remember the roots & heritage of languages when trying to understand their constructs. Ruby shares the "More Than One Way To Do It" philosophy with Perl, and idiomatic Ruby code often has a high emphasis on elegance.
The "post-expression"-style conditionals are a good example of this. If I have guard expressions at the start of my methods, it's not uncommon for me to write:
raise "Pre-condition x not met" unless x # (or "if !x" , preference thing)
raise "Pre-condition y not met" unless y # etc., etc.
instead of
if !x
raise "Pre-condition x not met"
end
if !y
raise "Pre-condition y not met"
end

Resources