Precedence of operators in ruby [duplicate] - ruby

This question already has answers here:
Operator precedence for And/&& in Ruby [duplicate]
(5 answers)
What's the precedence of ruby's method call
(4 answers)
Closed 9 years ago.
I tried code like this in ruby:
if object && object.is? ball
object.throw!
end
This resulted in a syntax error:
unexpected tIDENTIFIER, expecting keyword_then or ';' or '\n'
I figure this is because && must have a higher "precedence" than a function call (I'm sorry, I don't know the correct terminology) and so Ruby essentially saw the statement as:
if (object && object.is?) ball
object.throw!
end
which makes no sense and so a syntax error is in order.
This is further supported by the fact that this DOES work:
if object and object.is? ball
object.throw!
end
I presume it is because the 'and' operator has a lower precedence than &&, so the "precedence" of a function call must be somewhere between && and 'and'.
However, in the precedence order tables I have seen before, function calls are not listed.
I would appreciate some insight into what is happening here, and perhaps some references to the ruby specification. I am not an expert in expression resolution, I am just interested in learning more about the processes, problems and theory behind this example of, no doubt, a wider topic

Because of Operator Precedence, you should either do:
if object && (object.is? ball)
or
if object && object.is?(ball)
The reason is "&&" and "||" have higher precedence than "and" and "or". Thus if you don't use parenthesis for the latter "object.is? ball", "object.is?" will be grabbed first by "&&". However, if you use "and" without parenthesis, it works fine, since it has lowest priority in this case:
if object and object.is? ball

Related

What does :^ stand for in Ruby?

Not sure if I am searching in a wrong way, but couldn't find the answer anywhere online...
What does :^ stand for in Ruby? In particular trying to understand the code below:
# this returns the element in array_of_numbers, which occurs an odd number of times
array_of_numbers.reduce(:^)
# this returns 0
[1,2,3].reduce(:^)
# this returns 4
[1,2,3,4].reduce(:^)
Was tying to understand the logic playing with different arrays, but I think I am missing something. Thanks in advance!
: in front of a name produces a Symbol.
In some contexts, a Symbol can be used as a message to an object. The object that receives the message reacts to it by calling its method that has the same name as the symbol (if such a method exists).
In your examples, this method is Integer#^, which represent the exclusive OR bit operator.
[1,2,3].reduce(:^) is, more or less, the same as 1 ^ 2 ^ 3.*
Being an OOP language, 1 ^ 2 ^ 3 in Ruby is syntactic sugar for (1.^(2)).^(3).
Read more about the exclusive OR bit operator.
* They produce the same result but the explicit expression should be faster.

Why does the block of this if statement seem to be executed before the conditional in ruby? [duplicate]

This question already has answers here:
Undefined local variable based on syntax in Ruby
(1 answer)
Variable scope and order of parsing vs. operations: Assignment in an "if"
(3 answers)
Closed 7 years ago.
I'm currently working on a codegolf challenge, and so I'm trying to use as few characters as possible.
This code:
#example data
x=[1,2,3]
a=5.times.map{5.times.map{' '}}
#problematic code:
a[b][c]=x.pop if a[b=rand(5)][c=rand(5)] == ' '
returns a (quite strange) error:
test.rb:5:in `<main>': undefined local variable or method `b' for main:Object (NameError)
Did you mean? b
Which boils down to "Can't find b, did you mean b?". (to which the answer is yes).
This only happens with a 2D array with an inline if statement.
This code also runs fine:
if a[b=rand(5)][c=rand(5)] == ' '
a[b][c]=x.pop
end
It seems like it should be exactly the same, but it behaves differently. Why is this?
I thought it might have something to do with precedence, but I had a look at the ruby precedence table and everything would seem to be what I expect, so I'm not sure.

TCL how to require both operands to determine result in IF statement

new to TCL and running into a short circuit issue it seems. Coming from vbscript, I'm able to perform this properly, but trying to convert to a TCL script I'm having issues with the short circuit side effect and have been trying to find the proper way of doing this.
In the following snippet, I want to execute "do something" only if BOTH sides are true, but because of short circuiting, it will only evaluate the second argument if the first fails to determine the value of the expression.
if {$basehour != 23 && $hours != 0} {
do something
}
Maybe I'm not searching for the right things, but so far I've been unable to find the solution. Any tips would be appreciated.
The && operator always does short-circuiting in Tcl (as it does in C and Java and a number of other languages too). If you want the other version and can guarantee that both sub-expressions yield booleans (e.g., they come from equality tests such as you're doing) then you can use the & operator instead, which does bit-wise AND and will do what you want when working on bools. If you're doing this, it's wise to put parentheses around the sub-expressions for clarity; while everyone remember the precedence of == with respect to &&, the order w.r.t. & is often forgotten. (The parentheses are free in terms of execution cost.)
if {($basehour != 23) & ($hours != 0)} {
do something
}
However, it's usually not necessary to do this. If you're wanting an AND that you're feeding into a boolean test (e.g., the if command's expression) then there's no reason to not short-circuit, as in your original code; if the first clause gives false, the second one won't change what value the overall expression produces.

What is the purpose of "!" and "?" at the end of method names?

Sometimes I see methods in Ruby that have "?" and "!" at the end of them, e.g:
name = "sample_string"
name.reverse
name.reverse!
name.is_binary_data?
I was wondering what their purpose is? Are they just syntax sugarcoating?
It's "just sugarcoating" for readability, but they do have common meanings:
Methods ending in ! perform some permanent or potentially dangerous change; for example:
Enumerable#sort returns a sorted version of the object while Enumerable#sort! sorts it in place.
In Rails, ActiveRecord::Base#save returns false if saving failed, while ActiveRecord::Base#save! raises an exception.
Kernel::exit causes a script to exit, while Kernel::exit! does so immediately, bypassing any exit handlers.
Methods ending in ? return a boolean, which makes the code flow even more intuitively like a sentence — if number.zero? reads like "if the number is zero", but if number.zero just looks weird.
In your example, name.reverse evaluates to a reversed string, but only after the name.reverse! line does the name variable actually contain the reversed name. name.is_binary_data? looks like "is name binary data?".
Question mark indicates that the method returns boolean. Already answered here:
What does the question mark operator mean in Ruby?
The bang indicates that the method acts on the object itself. Already answered here:
Why are exclamation marks used in Ruby methods?
In Ruby the ? means that the method is going to return a boolean and the ! modifies the object it was called on. They are there to improve readability when looking at the code.
In contrast to the – I suppose – majority of programming languages ...
Ruby, methods are allowed to end with question marks or exclamation marks.
By convention, methods that answer questions (i.e. Array#empty? returns true if the receiver is empty) end in question marks.
Potentially “dangerous” methods (ie methods that modify self or the arguments, exit! etc.) by convention end with exclamation marks.
From: http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/, Section Funny method names
Beware, this isn't always the case. Take for example, Ruby Array#concat http://docs.ruby-lang.org/en/2.0.0/Array.html#method-i-concat.
Where you can get burnt badly is something like MyActiveRecordModel.column_names.concat([url]). Later calls related to MyActiveRecordModel will try to look for a column of 'url' for MyActiveRecordModel and throw.
Instead you must clone it before doing the concat. Fortunately my test suite caught this one, but.. heads up!

No increment operator (++) in Ruby? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why doesn't Ruby support i++ or i— for fixnum?
Why is there no increment operator in Ruby?
e.g.
i++
++i
Is the ++ operator used for something else? Is there a real reason for this?
Ruby has no pre/post increment/decrement operator. For instance, x++ or x-- will fail to parse. More importantly, ++x or --x will do nothing! In fact, they behave as multiple unary prefix operators: -x == ---x == -----x == ...... To increment a number, simply write x += 1.
Taken from "Things That Newcomers to Ruby Should Know
" (archive, mirror)
That explains it better than I ever could.
EDIT: and the reason from the language author himself (source):
++ and -- are NOT reserved operator in Ruby.
C's increment/decrement operators are in fact hidden assignment. They affect variables, not objects. You cannot accomplish assignment via method. Ruby uses +=/-= operator instead.
self cannot be a target of assignment. In addition, altering the value of integer 1 might cause severe confusion throughout the program.
From a posting by Matz:
(1) ++ and -- are NOT reserved
operator in Ruby.
(2) C's increment/decrement
operators are in fact hidden
assignment.
They affect variables, not objects. You cannot accomplish
assignment via method. Ruby uses +=/-= operator instead.
(3) self cannot be a target of
assignment. In addition, altering
the value of integer 1 might cause severe confusion throughout
the program.
matz.
I don't think that notation is available because—unlike say PHP or C—everything in Ruby is an object.
Sure you could use $var=0; $var++ in PHP, but that's because it's a variable and not an object. Therefore, $var = new stdClass(); $var++ would probably throw an error.
I'm not a Ruby or RoR programmer, so I'm sure someone can verify the above or rectify it if it's inaccurate.

Resources