Ruby: What does the snippet: (num & 1) == 0 exactly do?
&
is a bitwise AND operator. Doing (num & 1)
checks if the last bit (least significant bit) of the number is set. If it is set, the number is odd, and if it is not set, it is even.
It is just a fast way to check if a number is even or odd.
You can see a list of the ruby bitwise operators here: http://www.techotopia.com/index.php/Ruby_Operators#Ruby_Bitwise_Operators
Why does my method predefine the argument `(num=nil)`?
Whenever you define a method in Ruby, you can make it have arguments. When the method is called, the arguments are replaced by objects of your choosing. When you define an argument in the method definition, it becomes the default value.
For example, if you simply call my_count
in a program, it will automatically choose num
to be nil
, since no argument was explicitly provided. Otherwise, if you called my_count(5)
, then num
in the method will be 5.
Here is another example, with the default value as an empty hash. I will create two Server
objects:
class Server
attr_accessor :name
attr_accessor :files
def initialize(name, files={})
@name = name
@files = files
end
end
# Supply hash of files
Server.new('hostname', {'filename' => '2015-08-21 13:49 -4000'})
# New server will have no files -- empty hash
Server.new('hostname')
Let's change the initialize
method and create one last server:
class Server
attr_accessor :name
attr_accessor :files
def initialize(name, files) # No default value for files
@name = name
@files = files
end
end
Server.new('hostname', 'path/to/files/')
# => ArgumentError: wrong number of arguments (1 for 2)
In the modified class, I only supplied 1 argument, the name. Because files
no longer has a default value, then not including the argument raises an error. To clarify, omitting an argument is only allowed when the method definition has a default value for the argument. Without a default value, nothing will be used (not nil
, 0
, or ''
), and the program will stop/crash -- an error has been raised/encountered.
It is possible to create a method without arguments. Here is an example using String#length
. You will see that .length
does not take an argument, and instead works on the string.
string = 'Hello, world!'
string.length
# => 13
Bit flags operation
The spec should list the available flags and you can then just use the individual bits to toggle them on/off.
For instance the Python ssl module has multiple constants that we can use to change some options (flags).
Let's see if TLS version 1.0 option is enabled:
>>> import ssl
>>> ctx = ssl.create_default_context()
>>> bin(ctx.options)
'0b10000010010100100000000001010100'
>>> int(ssl.PROTOCOL_TLSv1)
3
>>> bin(ssl.PROTOCOL_TLSv1)
'0b11'
>>> bool(ctx.options & ssl.PROTOCOL_TLSv1)
False
We can see that the first two bits (3 in decimal) are not set and therefore this option is not enabled so let's enable it:
>>> ctx.options |= ssl.PROTOCOL_TLSv1
>>> bin(ctx.options)
'0b10000010010100100000000001010111'
>>> bool(ctx.options & ssl.PROTOCOL_TLSv1)
True
I guess this has a similar purpose in your case.
Ruby: difference between &= and &&=
Try the following:
x = 5
x |= 2
=> 7
|= and &= are equivalent to the bitwise x = x | 2 and x = x & 2
vs
x = 5
x ||= 2
=> 5
In the second statement, x ||= 2
, it means x = 2
if x is nil, otherwise it's x.
( x = (x || 2)
; the expression x || 2
returns x if x is anything but nil otherwise it returns 2.
x ||= 'foo'
is actually very common in Ruby (set x to foo is x is not already set)
x = (x & 3)
(which is equivalent to x &= 3
), returns 3 (the second operand) unless x is 0, it returns 0)
)
The same logic applies for & but it was easier to find an example on the top of my mind for |
=)
Ruby unfamiliar string usage with Integer.chr and \001
To make the code work in Ruby 1.9, try changing that line to:
flag = @data[2].ord & 2
Prior to Ruby 1.9, str[n]
would return an integer between 0 and 255, but in Ruby 1.9 with its new unicode support, str[n]
returns a character (string of length 1). To get the integer instead of character, you can call .ord
on the character.
The &
operator is just the standard bitwise AND operator common to C, Ruby, and many other languages.
Byte number three (0x03) is not a printable ASCII character, so when you have that byte in a string and call inspect
ruby denotes that byte as \003
. Just make sure you understand that "\003" is a single-byte string while '\003' is a four-byte string.
In Ruby, strings are really sequences of bytes. In Ruby 1.9, there is also encoding information, but they are still really just a sequence of bytes.
Why do these two snippets produce different results?
I figured out the problem. It's an error in my ruby code.
MEMO = Array.new(10, Array.new(10, Array.new(21, 0)))
If you were to print out the object ids of MEMO[0]
and MEMO[1]
you would find that they are the exact same. What I assumed Array.new(10, Array.new)
would do is create an Array
with 10 different Array
objects inside of it. Instead it creates an Array
of 10 references to the same Array
object.
By changing the first line to something like this:
MEMO = Array.new
10.times do
MEMO << Array.new
10.times do
MEMO[-1] << Array.new(21, 0)
end
end
or even simpler
MEMO = Array.new(10) {Array.new(10) {Array.new(21) {0}}}
It works perfectly fine.
Why does adding 1 to a recursive proc call return the count of calls made?
I just added some puts
to your code, maybe it helps to follow the logic better than I can explain with my english.
So, this is the tweaked code:
def rcall(num)
if 10 == num
rec = 0
puts "rec = #{rec} ---- End of recursion"
return rec
end
rec = rcall(num - 1)
res = 1 + rec
puts "rec = #{rec} \t\t res = i + rec = #{res}"
res
end
When you call on 15
for example, you get:
rcall(15)
# rec = 0 ---- End of recursion
# rec = 0 res = i + rec = 1
# rec = 1 res = i + rec = 2
# rec = 2 res = i + rec = 3
# rec = 3 res = i + rec = 4
# rec = 4 res = i + rec = 5
# 5
If you call on a number less than 10
, you never reach the end of the recursion, so no value is returned to build back the "call stack" and the error is raised: stack level too deep (SystemStackError)
Other languages supports recursion, for example Python. Here on famous Fibonacci (How to write the Fibonacci Sequence?).
I also want to share this Computerphile video about recursion on YouTube: https://youtu.be/Mv9NEXX1VHc
Related Topics
What's the Difference Between Controllers and Actions in Ruby on Rails
How to Stop the Rails Debugger for the Current Request
How to Call Rake Tasks That Are Defined in the Standard Rakefile from an Other Ruby Script
Framework for Non-Web Ruby Project
Mongodb and Mongoid in Production
Ruby - Adding a Directory to $Load_Path - What Does It Do
Getting Memory Usage of My Process from Osx Using Ruby
Rails - How to Create a Model Linked to Two of Another Model
Ruby: Cannot Parse Excel File Exported as CSV in Os X
How to Match Unicode Words with Ruby 1.9
Paperclip :Style Depending on Model (Has_Many Polymorphic Images)
Convert Unicode into Character with Ruby
Token Based Authentication for Rails JSON APIs
Parsing Simple Xml with Nokogiri
Difference Between .Nil, .Blank? and .Empty
I Need to Generate Uuid for My Rails Application. What Are the Options(Gems) I Have