Why symbol is not equal to symbol - ruby

I did:
x = :foo, y = %q{foo}.to_sym, x.==(y)
# => [:foo, :foo, false]
I am wondering why :foo is not equal to :foo.

Parallel assignment works differently in Ruby, and if you want multiple statements on one line, you need to separate them with semicolons (not commas).
The statement you executed:
x = :foo, y = %q{foo}.to_sym, x == y
Is equivalent to:
x = [:foo, y = %q{foo}.to_sym, x == y]
N.B. x is not yet defined when the right-hand side of the expression is evaluated, so the last term is effectively comparing nil and :foo. The y assignment also happens while the right-hand side of the expression is evaluating, and the result gets included in the array literal being assigned to x.
Here's what you meant to do:
x, y = :foo, %q{foo}.to_sym; x == y # => true
Just an aside, x.==(y) works because :== is technically a method, but in idiomatic Ruby you just write x == y. The interpreter knows what you mean.

Nice answer, but there is a logical leap from "x is not yet defined" to "the last term is effectively comparing nil and :foo.", in particular, why an undefined variable is evaluated as nil is unexplained.
This has to do with how variable hoisting is implemented in Ruby. It's an obnoxious feature of JavaScript too.

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.

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?

Official expansion of ||= conditional assignment operator

I want to emphasize I am looking for the actual way the ||= operator is expanded by the Ruby 1.9.3 interpreter, not how it appears to be expanded based on its behavior. What I'm really hoping for is someone who has grokked the actual interpreter source, a task which I sadly am probably not up to. The only resource I have found that appears to examine this question is out of date: "A short-circuit (||=) edge case".
The resource I mentioned above seems to suggest that the "official" expansion of x ||= y to x = x || y was either inaccurate or buggy in interpreter versions prior to 1.9. In any case, the edge case indicated seems to have been smoothed out. The resource above claims that x || x = y or x or x = y are "more accurate". Neither of those, however, is correct, because they don't work when x is a previously undeclared global variable:
[11:04:18][****#asha:~]$ irb
1.9.3-p194 :001 > a || a = 3
NameError: undefined local variable or method `a' for main:Object
1.9.3-p194 :002 > b or b = 3
NameError: undefined local variable or method `b' for main:Object
1.9.3-p194 :003 > c = c || 3
=> 3
So in 1.9.3, at least, the x = x || y expansion appears to be correct, as far as these examples are concerned. However, to reiterate my original point, I would really like to see some truly authoritative source resolve this question, well, authoritatively rather than anecdotally as I (and others) have done.
x ||= y
is a shorthand form for
x || x = y
If x is not nil and x is not false, the assignation will have place because of the short-circuit evaluation of the || operator.
EDIT: This post is about the spec, read the comments to get the somewhat less ideal "implementation story"
The Ruby draft spec (PDF) section 11.4.2.3.2 defines it fairly specifically (even if fairly hard to interpret); let's do a (theoretically somewhat loose) example with c ||= 3;
a) Evaluate the variable as a variable reference (see 11.5.4). Let V be the resulting value.
V is set to the value of c
b) Evaluate the operator-expression or the method-invocation-without-parentheses. Let W be the resulting value.
W is set to 3.
c) Let OP be the assignment-operator-name of the assignment-operator.
OP is set to ||
d) Let X be the operator-expression of the form V OP W.
X is set to c || 3.
e) Let I be the variable of the abbreviated-variable-assignment-expression or the abbreviated- variable-assignment-statement.
I is set to refer to c.
f) Evaluate a single-variable-assignment-expression (see 11.4.2.2.2) where its variable is I and the operator-expression is X.
c = c || 3 is evaluated.
g) The value of the abbreviated-variable-assignment is the resulting value of the evaluation.
The result of the assignment is 3.
In other words, the expansion c = c || 3 is (excluding bugs like in pre-1.9) correct.

"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

What does ||= mean in Ruby? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What does ||= mean in Ruby?
What does ||= mean in Ruby?
It's mainly used as a shortform for initializing a variable to a certain value, if it is not yet set.
Think about the statement as returning x || (x = y). If x has a value (other than false), only the left side of the || will be evalutated (since || short-circuts), and x will be not be reassigned. However, if x is false or nil, the right side will be evaluated, which will set x to y, and y will be returned (the result of an assignment statement is the right-hand side).
See http://dablog.rubypal.com/2008/3/25/a-short-circuit-edge-case for more discussion.
x ||= y is often used instead of x = y if x == nil
The idea is the same as with other similar operators (+=, *=, etc):
a ||= b is a = a || b
And this trick is not limited to Ruby only: it goes through many languages with C roots.
edit to repel downvoters.
See one of Jörg's links for more accurate approximation, for example this one.
This is exactly why I don't like Ruby: nothing's ever what it seems.

Resources