Shift Operators
The <<
and >>
operators are for shifting. In many programming languages this is limited to the idea of bit shifting operators. But was with many operators in Ruby, the semantics of an operator are projected into other contexts. We don't just shift integers, we can shift things like Dates.
Bit Shifting
Here are some examples of how bit shifting to the left and then to the right works. This are closely inspired by what is in the Ruby docs.
> n = 0b11110
=> 30
> "%08b" % (n << 1)
=> "00111100"
> "%08b" % (n << 3)
=> "11110000"
> "%08b" % (n << -1)
=> "00001111"
> "%08b" % (n << -3)
=> "00000011"
> "%08b" % (n >> 1)
=> "00001111"
> "%08b" % (n >> 3)
=> "00000011"
We output things as binary (using Percent String Formatting). As a result, we can see the bits shift to the left and then to the right.
Shifting Left
The <<
operator is overridden by many classes with the semantic meaning of shoveling an object into a container. To dig deeper into this, head over to the Shovel Operator page.
Shifting Dates
When used with a Date
object, the <<
and >>
operators shift the date to the left or the right by the number of months.
> require 'date'
=> true
> d = Date.new(1995, 12, 25)
=> #<Date: 1995-12-25 ((2450077j,0s,0n),+0s,2299161j)>
> d << 1
=> #<Date: 1995-11-25 ((2450047j,0s,0n),+0s,2299161j)>
> d >> 1
=> #<Date: 1996-01-25 ((2450108j,0s,0n),+0s,2299161j)>
> d << 3
=> #<Date: 1995-09-25 ((2449986j,0s,0n),+0s,2299161j)>
> d >> 3
=> #<Date: 1996-03-25 ((2450168j,0s,0n),+0s,2299161j)>
Composing Functions
Multiple lambdas or procs can be composed with >>
. The composite function will run the composed functions left to right, passing the output from one as input to the next.
Here is an example of combining a series of text transformations into a single function.
> strip_whitespace = ->(str) { str.strip }
=> #<Proc:0x00007fdb479d8cd8 (irb):329 (lambda)>
> capitalize = ->(str) { str.capitalize }
=> #<Proc:0x00007fdb4293fdd0 (irb):330 (lambda)>
> exclaim = ->(str) { str + "!" }
=> #<Proc:0x00007fdb4404f700 (irb):331 (lambda)>
> format_text = strip_whitespace >> capitalize >> exclaim
=> #<Proc:0x00007fdb429ad970 (lambda)>
> format_text[" Hello, Ruby "]
=> "Hello, ruby!"
Since operators are methods implemented on a class, this is just another example of an operator being repurposed to do something useful in a specific class context.