Looking up how to calculate the factorial of a number I came across this code:
(1..5).inject(:*) || 1 # => 120
What is the (:*) || 1 doing?
How does it compare to this line of code (1..5).inject(1) { |x, y| x * y } # => 120, which uses .inject to achieve similar functionality?
Colon-star in itself doesn't mean anything in Ruby. It's just a symbol and you can pass a symbol to the inject method of an enumerable. That symbol names a method or operator to be used on the elements of the enumerable.
So e.g.:
(1..5).inject(:*) #=> 1 * 2 * 3 * 4 * 5 = 120
(1..5).inject(:+) #=> 1 + 2 + 3 + 4 + 5 = 15
The || 1 part means that if inject returns a falsey value, 1 is used instead. (Which in your example will never happen.)
test.rb:
def do_stuff(binary_function)
2.send(binary_function, 3)
end
p do_stuff(:+)
p do_stuff(:*)
$ ruby test.rb
5
6
If you pass a method name as a symbol, it can be called via send. This is what inject and friends are doing.
About the || part, in case the left hand side returns nil or false, lhs || 1 will return 1
It's absolutely equal. You may use each way, up to your taste.
Related
In Ruby, the operator precedence is (implicitly) defined, and documented in a couple of places, for example at Ruby operator precedence table.
Some languages allow setting or changing the operator precedence, for example in Prolog: https://www.swi-prolog.org/pldoc/man?predicate=op/3.
Is that possible in Ruby too?
For example switching the order of addition and multiplication:
1 + 2 * 3 + 4
# => standard precedence results in 1 + 6 + 4 => 11
1 + 2 * 3 + 4
# => changed precedence would result in 3 * 7 => 21
I had the same question regarding the AoC's problem of today, but I found this old issue:
https://bugs.ruby-lang.org/issues/7336
So I guess it's not feasible.
OK, changing operator precedence in Ruby is explicitly stated as not possible. I found a naughty solution though that I'll share for fun, using hack-ishly overloading two operators that have similar or higher precedence than another one.
class Integer
def %(operand)
# `%` has same precedence as `*`.
self + operand
end
def **(operand)
# `**` has higher precedence than `*`.
self + operand
end
end
puts eval("1 + 2 * 3 + 4")
# => 11
puts eval("1 % 2 * 3 % 4")
# => 13
puts eval("1 ** 2 * 3 ** 4")
# => 21
Don't do this in production code...
For example:
def recurse(value)
if value < 5
self.send(__method__, value + 1)
else
value
end
end
This works, but it's a bit ugly.
Basically I'm looking for a prettier way to call the currently executing method, without referring to it explicitly by name.
If there is a less-cryptic syntax for this, I would probably use it (to avoid the name duplication, reduce effort required for renaming a function, etc). If there isn't a nicer syntax for this, I'll just hard-code the name like normal.
It's a comment rather, as #sagarpandya82 mentioned, you can omit some redundant parts and use both variants. I would refactor it a bit:
def recurse(value)
return value unless value < 5 # return value if value >= 5
send(__method__, value + 1) # or just recurse(value + 1)
end
Non-recursion version with a block:
def non_recurse(value)
if value >= 5
yield value
else
(value..5).each do |i|
yield i
end
end
end
non_recurse(3) {|i| puts i}
#=> 3, 4, 5
non_recurse(6) {|i| puts i}
#=> 6
If you really want to use __method__, your method is correct and reasonably readable. To comply with usual Ruby guidelines, you could just remove returns and use 2 spaces as indent (as mentioned by #sagarpandya82 in the comments):
def recurse(value)
if value < 5
self.send(__method__, value + 1)
else
value
end
end
I don't see any reason to use self.send(__method__) here, so you could write :
def recurse(value)
if value < 5
recurse(value + 1)
else
value
end
end
Actually, I'd say that you don't need recursion at all. All your method does is to keep adding 1 to the value until it reaches 5. If the value is bigger than 5, it returns the value :
For integers:
def no_recurse(value)
[value, 5].max
end
no_recurse(4)
# 5
no_recurse(-3)
# 5
no_recurse(7)
# 7
no_recurse(-2**1000)
# 5
no_recurse(4.5)
# 5 # <- That's wrong
For floats, you'd just need to add the decimal part to 5. This will work for any number:
def no_recurse(value)
[value, 5 + value % 1].max
end
no_recurse(4.5)
# 5.5
no_recurse(5.5)
# 5.5
no_recurse(6)
# 6
no_recurse(-7)
# 5
Coming from Python I find the following behaviour very surprising:
irb(main):211:0> x= 33
=> 33
irb(main):212:0> x[0]
=> 1
irb(main):213:0> x[1]
=> 0
irb(main):214:0> x[2]
=> 0
Is there a rationale/philosophy for not raising an error in this example?
The bracket operator gives you the nth bit of the binary representation:
http://ruby-doc.org/core-2.1.2/Fixnum.html#method-i-5B-5D
You might be a little confused about what this is doing internally, but that's normal when dealing with Ruby because it's quite unlike other scripting languages. Unless you've used SmallTalk it might even seem insane.
When Ruby sees the following code:
x = 6
x[1]
What it's actually doing is this:
x.send(:[], 6) # Send :[] method call to x with arguments [ 6 ]
The x object is free to interpret that however it wants, and the behaviour is typically (though not always) defined by the class x belongs to if x is a normal instance.
In this case it's returning the bit at a given index, equivalent to x & (1 << 6) >> 6.
Sometimes the [] method does several things:
string = "brackets"
# Retrieve a single character
string[1]
# => "r"
# Retrieve a substring
string[5,2]
# => "et"
# Perform a pattern match
string[/[^aeiou]+/]
# => "br"
This also does some pretty crazy things since you can apply it to a Proc as well:
fn = lambda { |x| x + 1 }
# Conventional (explicit) call
fn.call(2)
# => 3
# Square bracket method
fn[5]
# => 6
Since Ruby leans very heavily on Duck Typing, this means that you can write a Proc to fill in where you'd normally have a Hash or an Array and the method receiving your object is none the wiser.
It's this flexibility in leaving the meaning of x[...] for your own class instance x up to you that makes it pretty powerful.
For example:
class Bracketeer
def [](i)
"%d brackets" % i
end
end
bracketeer = Bracketeer.new
bracketeer[6]
# => "6 brackets"
This simple notation often comes in handy when you're trying to create a minimal interface for a class of yours. In many cases you can use something simple like [] to replace what would be a more verbose method like find_by_id or cache_fetch.
Certainly. You'll find that the manual is quite illuminating.
This is returning the binary bit for the bit position value as a zero or one.
It is returning the n'th bit as rightfully observed by #msergeant.
What this means is, for the number 33, its binary representation is:
Index : [7][6][5][4] [3][2][1][0]
Bits : 0 0 1 0 0 0 0 1
Which explains the output:
irb(main):212:0> x[0]
=> 1
irb(main):213:0> x[1]
=> 0
irb(main):214:0> x[2]
=> 0
I am new to Ruby.
I found this code while reading a tutorial
10.times { |i | print i, " " } # o/p => 0 1 2 3 4 5 6 7 8 9
I know times repeat a action number of times it's called.
I assume that i gets initialised to 0.
But, how it's getting incremented?
I assume that i gets initialised to 0. But, how it's getting incremented?
There's an internal variable, the integer itself doesn't change. Let's implement our own times method using a basic while loop:
class Integer
def my_times
i = 0 # initialize to 0
while i < self # self is the integer object, i.e. 10
yield i # pass i to the block
i += 1 # increment i
end
end
end
Usage:
10.my_times { |i| print i, " " } #=> 0 1 2 3 4 5 6 7 8 9
The Ruby method is more complex (returning an enumerator without a block), but you get the idea.
times creates an array of incrementing numbers (well an Enumerator actually, but it can be converted to an array with to_a)
$ irb
irb(main):001:0> 3.times.to_a
=> [0, 1, 2]
irb(main):002:0> 10.times.to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
See: http://www.ruby-doc.org/core-2.2.0/Integer.html#method-i-times
each is an Array/Enumerator method that yields each element.
See:
http://www.ruby-doc.org/core-2.2.0/Array.html#method-i-each
http://www.ruby-doc.org/core-2.0.0/Enumerator.html#method-i-each
In Ruby, everything is an object, including numbers. The integers are objects, meaning, they are defined from an Integer class that contains methods. Those methods can be called on an instance of the object. Thus, the number 10 is an instance object of the Integer class and you can call methods on it.
One of those methods is times. When you do:
10.times ...
You are calling the times method on the object 10. This method accepts a block parameter {...}:
10.times { |i| puts i }
Here, the i is the parameter for the block and the times method internally has a loop that runs that parameter from 0 to the object integer you called the times method on.
As #MarekLipka said in a comment, see the documentation for the Ruby Integer class.
In recursion, a method calls itself. I'm not following it when there are return values. For example, in the "Learn to Program" book by Chris Pine, there is this example on factorials.
def factorial num
if num < 0
return 'You cant\'t take the factorial of a negative number!'
end
if num <= 1
1
else
num * factorial(num-1)
end
end
If I call the method factorial(3), it will go to the else portion of the code and will look like this:
3 * factorial(3-1)
and should return 6 since 3*2=6. factorial(3-1) calls the factorial method passing 2 within the recursion. num = 2, and thus 2 * factorial(2-1) and 2*1=2.
What happens to the 6 that we got from our first run through the code? Now that num = 1, it looks like this will now return 1 and go to the end of the code. But from my understanding, we still have 6 and 2 from the previous recursions. Am I correct in this assumption, since we called the factorial function when we multiplied by num? Can someone help me understand this better? Say we called factorial(10), how would this work out?
Now what happens to the 6 that we got from our first run through the
code?
There was no 6 from the first run; the 6 only appeared at the end.
This is what happens:
factorial(3) → 3 * factorial(2)
factorial(3) → 3 * 2 * factorial(1)
factorial(3) → 3 * 2 * 1
There is no “memory” of previous calls in your function, each time factorial() is called, it's like a brand new function; is it clearer when written as multiple functions?
def factorialof3
3 * factorialof2
end
def factorialof2
2 * factorialof1
end
def factorialof1
1
end
Patrice answer splitting it up into separate functions is good, and if you have any background in computer science, it will also help to think of what data structures are probably at work here, mainly the Stack
So when you call factorial(3) it will go to that else block and 'stack' on another call to factorial(2)
and then stack another one with a call to factorial(1).
at that point, since num = 1, (recursion must always have a base case) factorial(1) will return 1.
Then because of the stack, the last one in is the first one out, so the factorial(1) will return 1, and that will 'fall' back down to the factorial(2) call, and because it was called in that else block, the call to factorial(2-1) will now be replaced by 1, and you will get 2*1, and I think by now you get the picture
It is also important to note, this example is trying to teach you recursion in general, and this example is not really idiomatic ruby. The solution alfasin posted as a comment is more like it.
First, you should replace your return 'blabla' with a raise 'blabla' because your function returns a numeric, not a string.
Then see it like this
factorial(3)
3 * factorial(2)
2 * factorial(1)
1 # no more recursion, let's go up replacing
# the function calls by the returned value
end
end
end
# ↓
factorial(3)
3 * factorial(2)
2 * 1 # let's go up again !
end
end
# ↓
factorial(3)
3 * 2 # finally
end
# ↓
6