Wikia

ROM Hack City

Watchlist Recent changes

Ruby operators

These links redirect here: Ruby operator, Ruby operator precedence, Ruby order, Ruby order of operations.


This page is about the operators in Ruby 1.9.

Contents

Operator precedence Edit

When Ruby encounters two operators, and must evaluate one operator to use the result with the other operator, then the Ruby operator precedence, or Ruby order of operations, determines the first operator to evaluate.

  • So 2 + 2 * 2 acts like 2 + (2 * 2), because multiplication * has precedence before addition + in Ruby.
  • So 2 + 2 == 2 * 2 acts like (2 + 2) == (2 * 2), because equality == has the lowest precedence; but 2 + 2 happens before 2 * 2, because Ruby does not need the result from 2 * 2 to compute 2 + 2.

The order in Ruby is like the order in C language or in Perl, but is not exactly the same. Ruby has higher precedence for & | ^.

Operator Associativity
-1.9 not associative
() [] {} defined?() not() super() yield()

'' "" `` // %Q %q %W %w %x %r %s << <<-

begin if unless while until case class module def (control structures)

not associative
. ::

[] (method)

left to right
 ! ~ + (unary) right to left
** right to left
- (unary) right to left
* / % left to right
+ - (binary) left to right
<< >> left to right
& left to right
| ^ left to right
> >= < <= left to right
<=> == === != =~ !~ not associative
&& left to right
|| left to right
.. ... not associative
 ?: right to left
rescue (modifier) left to right
= **= *= <<= >>= &&= &= ||= |= += -= /= ^= %= right to left
defined? not associative
, => : not associative
not right to left
or and left to right
if unless while until (modifier) unknown
 ; left to right

Operator associativity Edit

Operator associativity is the order of evaluation in situations like a - b - 3.

  • Subtraction is left associative, so a - b - 3 acts like (a - b) - 3.
  • Assignment is right associative, so a = b = 3 acts like a = (b = 3).
  • Equality is not associative, so a == b == 3 raises SyntaxError.

Details Edit

TODO

Literals Edit

Operator Associativity
-1.9 not associative

A minus sign starting a literal Float or Integer, as in -1.9 or -0x8000, has a higher precedence than the unary minus operator.

  • So -1.9.abs acts like (-1.9).abs, because a literal has more precedence than a method call;
  • but -x.abs acts like -(x.abs), because the unary minus operator has less precedence than a method call.
0> -1.9.abs
=> 1.9
0> x = 1.9
=> 9
0> -x.abs
=> -1.9

Circumfix brackets Edit

Operator Associativity
() [] {} defined?() not() super() yield() ->

'' "" `` // %Q %q %W %w %x %r %s << <<-

begin if unless while until case class module def (control structures)

not associative

The operators with the most precedence are parentheses (), and everything that has the same precedence as parentheses. These operators have an opening bracket and a closing bracket. These are circumfix operators, because they surround (circumscribe) their operands.

Parentheses Edit

You can use parentheses to control the order of operations. If you want addition before multiplication, you can write (2 + 2) * 2.

0> (2 + 2) * 2
=> 8

Parentheses may contain multiple statements (like a progn in Common Lisp). Parentheses take the value of the last statement.

0> 2 + (puts "ROM hacking"; 2)
ROM hacking
=> 4
0> 2 + (sum = open("mario-paint.sfc") { |f| f.read }.sum 16
1>      printf "Checksum of Mario Paint is x%04x\n", sum
1>      2)
Checksum of Mario Paint is x4b9e
=> 4

Parentheses, that contain zero statements, return nil.

0> ()
=> nil

Parentheses act differently where they collect arguments to methods. The method arguments may not contain any operators below , or => in precedence.

Other brackets Edit

Square brackets [] either make an array literal, or collect arguments to the [] method. You use the comma , to separate the array elements or method arguments.

0> ["ROM", "hacking", "is", "fun"][1,3]
=> ["hacking", "is", "fun"]

Curly braces {} make a hash literal. You use the arrow => to map keys to values, and use the comma , to separate the key-value pairs.

0> {"Mario Paint" => File.stat("mario-paint.sfc").size,
1*  "Skipp and Friends" => File.stat("saf.sfc").size}
=> {"Mario Paint"=>1048576, "Skipp and Friends"=>1048576}

Quotes Edit

Quotes make a string literal. Some quotes allow interpolation.

0> %q<2 + 2 * 2 is #{2 + 2 * 2}>
=> "2 + 2 * 2 is \#{2 + 2 * 2}"
0> %Q<2 + 2 * 2 is #{2 + 2 * 2}>
=> "2 + 2 * 2 is 6"
0> "the #{result = 2 + 2 * 2; "result"} is " + result.to_s
=> "the result is 6"
0> %x<#{%x<echo echo>.chomp} shell command>
=> "shell command\n"

Control statements Edit

In a list of operators, I would probably never mention control statements like if or while. I mention them for Ruby, because Ruby allows them inside expressions. The first keyword acts as an opening bracket; the end keyword acts as a closing bracket; so control statements act as circumfix operators, and have the same precedence as parentheses.

You can use begin and end like parentheses, but you can also add rescue and else clauses.

0> 2 + begin; puts "ROM hacking"; 2; end
ROM hacking
=> 4
0> 2 + begin
1*       sum = open("mario-paint.sfc") { |f| f.read }.sum 16
1>       printf "Checksum of Mario Paint is x%04x\n", sum
1>       2
1>     end
Checksum of Mario Paint is x4b9e
=> 4

You can also put any of begin if unless while until case class module def in expressions.

0> "I tell you that " + if 5 > 3
1>                        "five is greater than three"
1>                      else
1*                        "you redefined Fixnum#> method"
1>                      end + "!"
=> "I tell you that five is greater than three!"
0> letter = ?x
=> "x"
0> "%#{letter} is for " + case letter
1>                        when ?q; "'single quotes'"
1>                        when ?Q; '"double quotes"'
1>                        when ?w; "single-quoted array of words"
1>                        when ?W; "double-quoted array of words"
1>                        when ?x; "`shell commands`"
1>                        when ?r; "/regular expressions/"
1>                        when ?s; ":symbols"
1>                        end
=> "%x is for `shell commands`"

Dots and colons Edit

Operator Associativity
. ::

[] (method)

left to right

We use the dot . operator to call methods.

  • The dot is left associative. So 3.next.next acts like (3.next).next, not 3.(next.next).
irb(main):006:0> 3.next.next
=> 5
irb(main):007:0> (3.next).next
=> 5
irb(main):008:0> 3.(next.next)
SyntaxError: ...

Calls to the [] method, whether you write a[b] or a.[](b), have the same precedence as the dot.

  • The [] operator is also left associative. So a[1][2] acts like (a[1])[2], not a([1][2]).
0> a = ["this", ["is", "a", "literal"], "array"]
=> ["this", ["is", "a", "literal"], "array"]
0> a[1][2]
=> "literal"
0> a.[](1).[](2)
=> "literal"
0> a[1].[](2)
=> "literal"
0> a.[](1)[2]
=> "literal"

The double-colon :: operator accesses the constant member of a module or class. For example, the Encoding class has a Encoding::Converter member. Encoding::Converter is also a class, and has a member Encoding::Converter::INVALID_MASK.

  • The double-colon is left associative. So Encoding::Converter::INVALID_MASK acts like (Encoding::Converter)::INVALID_MASK.

The double-colon works with any object that is a class or module.

0> Class.new { ROM = "Read-Only Memory" }::ROM
=> "Read-Only Memory"

If we define A::B.c to return File, then A::B.c::EXCL returns File::EXCL.

  • So A::B.c::EXCL acts like ((A::B).c)::EXCL, not A::(B.c)::EXCL nor (A::B).(c::EXCL). This shows that the dot and the double-colon have the same precedence.
0> module A
1>   module B
2>     def self.c; File; end
2>   end
1> end
=> nil
0> A::B.c::EXCL
=> 2048
0> ((A::B).c)::EXCL
=> 2048
0> A::(B.c)::EXCL
NameError: uninitialized constant B
...
0> (A::B).(c::EXCL)
NameError: undefined local variable or method `c' for main:Object
...

We can use the dot to call class methods or module methods (which are singleton methods of that class object or module object), or we can use the double-colon. So A::B::c::EXCL does work. So File.stat and File::stat are equivalent.

0> A::B::c::EXCL
=> 2048
0> File.stat("n-warp-daisakusen-1.0.sfc").size
=> 2097152
0> File::stat("n-warp-daisakusen-1.0.sfc").size
=> 2097152

If the object is not a class or module, then the double-colon can still call methods, like the dot does. We seem can replace any dot with a double-colon! (But not dots in floating-point literals.)

0> -1.9.abs
=> 1.9
0> -1.9::abs
=> 1.9
0> -1::9::abs
SyntaxError: ...
0> 2::+(2::*(2))
=> 6

My habit is to use the dot, never the double-colon, for all method calls; but you can use either way. The one exception is that if a constant and a method have the same name (though that almost never happens), then the double-colon returns the constant, so you must use the dot to call the method.

0> module A
1>   B = 3
1>   def self.B; 5; end
1> end
=> nil
0> A::B
=> 3
0> A.B
=> 5
0> A.const_get :B
=> 3
0> A.method(:B).call
=> 5

Reference Edit

  • ruby-1.9.1-p129/parse.y, including the "precedence table"

Pages on ROM Hack City

Add a Page
77pages on
this wiki
Advertisement | Your ad here

Latest Photos

Add a Photo
14photos on this wiki
See more >

Recent Wiki Activity

See more >

Around Wikia's network

Random Wiki