can someone explain what this line of ruby code does? - ruby

Found in the Ruby style guide.
1 > 2 ? true : false; puts 'Hi'
I assume this always returns Hi, but how do I read it?

If 1 > 2 then true, else it is false.
However, it will print hi whatever the condition result.
It is the same that:
if 1 > 2 then
true
else
false
end
puts 'hi'

You may read this like
1 > 2 ? true : false # first line of code
puts "Hi" #second line of code

The Ruby compiler reads it like this:
1.>( 2 )
puts "Hi"
Ternary operator ? : is redundant. Comparison 'greater than' symbol :> is actually a method of Numeric class.

If 1 is greater than 2 then true, else then false.
Then puts Hi
http://buddylindsey.com/c-vs-ruby-if-then-else/

The semicolon is an inline way of separating two lines of code. So it's just like
1 > 2 ? true : false
puts "Hi"
which is equivalent to
false
puts "Hi"
And of course a line that just says false will do nothing (except for a few cases, like if it's the last line of a function definition in which case the method returns false if it reaches that line).

1 > 2 ? true : false; puts "Hi" that means
if 1 > 2
return true
else
return false
end
puts "Hi"
Here each time means the result is whatever it will print "hi" because we print "Hi" in outside of condition.
but
if 1 > 2
puts "1 is not greater than 2"
else
puts "1 is greater than 2"
end
you can also test in your console
1.9.3p125 :002 > if 1 > 2
1.9.3p125 :003?> puts "1 is not greater than 2"
1.9.3p125 :004?> else
1.9.3p125 :005 > puts "1 is greater than 2"
1.9.3p125 :006?> end
1 is greater than 2
=> nil

Related

Why is my Ruby Code not processing the input?

STDIN.read.split("\n").each do |a|
a=gets.to_i
if a >=0
puts "a is positive"
end
end
Output
C:\Ruby221-x64\programs>ruby test2.rb
5
test2.rb:3:in `read': Interrupt
from test2.rb:3:in `<main>'
Question: Why is my Ruby Code not going into the if?
Also Is the above code a way to handle continuous input? how will my code know after which input to stop. I had to press Ctrl-C to come out
Your gets call is superfluous because the STDIN.read.split("\n").each do |a| already reads the inputs into a. So remove the gets:
STDIN.read.split("\n").each do |a|
if a.to_i >= 0
puts "#{a} is positive"
end
end
Note that the I/O is buffered, and you're operating on a block basis, so you'll get:
Enter these inputs:
5
4
3
Press Ctrl-D to end the input (for Linux) or Ctrl-Z (for Windows), then you'll get results:
5 is positive
4 is positive
3 is positive
=> ["5", "4", "3"]
If you want this to be more interactive, then don't use the STDIN... each construct, but just do a loop with gets.to_i. For example:
loop do
a = gets
break if a.nil? # Exit loop on EOF (ctrl-D)
if a.to_i > 0
puts "a is positive"
end
end
If I put this into a file, say foo.rb, then I get:
OS_Prompt> ruby foo.rb
3
a is positive
5
a is positive
2
a is positive
-1
-3
2
a is positive
[ctrl-D]
OS_Prompt>
And it will quit the loop on ctrl-D since that will cause gets to return nil. Although in Windows, it might want Ctrl-Z.
▶ loop do
▷ b = STDIN.gets.to_i
▷ break if b.zero?
▷ puts b > 0 ? 'positive' : 'negative'
▷ end
#⇒ 5
# positive
# -4
# negative
# 0
# => nil
STDIN.read.split("\n").each do |a|
This line is already taking input continuously then whats the need of gets.
while(true)
b= gets.chomp.to_i
puts b >=0 ? "b is positive" : "b is negative"
end
Here chomp is used to remove \n from the input

Ruby function to check if a number is divisible by five and is even

def is_even?(n)
remainder_when_divided_by_2 = n % 2
if remainder_when_divided_by_2 == 0
return true
else
return false
end
end
def is_odd?(n)
return ! is_even?(n)
end
puts "1 is_even? #{is_even?(1)} - is_odd? #{is_odd?(1)}"
puts "2 is_even? #{is_even?(2)} - is_odd? #{is_odd?(2)}"
puts "3 is_even? #{is_even?(3)} - is_odd? #{is_odd?(3)}"
puts "4 is_even? #{is_even?(4)} - is_odd? #{is_odd?(4)}"
puts "5 is_even? #{is_even?(5)} - is_odd? #{is_odd?(5)}"
puts "6 is_even? #{is_even?(6)} - is_odd? #{is_odd?(6)}"
def is_even_and_divisible_by_five?(n)
remainder_when_divided_by_five = n % 5
if (remainder_when_divided_by_five == 0) && (is_even?(n) == true)
return true
else
return false
end
end
puts "5 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(5)}"
puts "10 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(10)}"
puts "15 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(15)}"
puts "20 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(20)}"
puts "25 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(25)}"
puts "30 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(30)}"
The problem was I had not called the method is_even_and_divisible_by_five in the puts commands at the bottom of the code. I called it is_even_and_divisble_by_5. Then in the if statement in the is_even_and_divisble_by_five method, I left of the (n) arguement from Is_even. Thank you all very much!
Even (divisible by two) and divisible by five also means "divisible by ten":
def is_even_and_divisible_by_five?(n)
n % 10 == 0
end
You called
is_even_and_divisible_by_5?
instead of
is_even_and_divisible_by_five?
Also is_even? function is undefined. I guess there was some mistake made with its defining or maybe even not-defining. So maybe when you defined is_even_and_divisible_by_five?(n) function there were some other errors and It was not defined too. Plus I think here is much easier solution:
def is_even_and_divisible_by_five?(n)
n % 5 == 0 && n.even?
end
In Ruby You don't have to use return all the time. You should use it quite rarely. The reason is ruby functions return last calculated value by default. And nearly everything is returning value in ruby, even blocks and If-Else statements. If you open irb console and try to do some code, for example:
a = 5
=> 5
Second line is what first line returns. You can do some experiments like this by your own with any type of conditions you like.
The name of your method is is_even_and_divisible_by_five?, not is_even_and_divisible_by_5?.
is_even? is not defined by itself
Here a shorter version of your method
def is_even_and_divisible_by_five? n
0 == n % 5 + n % 2
end

How to intercept IRB input?

Is it possible to intercept IRB inputs? Specifically for class#Fixnum?
Example:
5
=> 5
What I need to do is: (pseudo code)
if IRB.input.is_a?(Fixnum)
some_method(IRB.input) # some_method(5)
end
Look at this file.
You can find Irb#eval_input method and patch them:
# code before
#scanner.set_input(#context.io) do
signal_status(:IN_INPUT) do
if l = #context.io.gets
if l.match(/^\d+$/)
puts 'Integer found!'
end
print l if #context.verbose?
else
if #context.ignore_eof? and #context.io.readable_after_eof?
l = "\n"
if #context.verbose?
printf "Use \"exit\" to leave %s\n", #context.ap_name
end
else
print "\n"
end
end
l
end
end
# code after
Irb output example:
spark#think:~$ irb
2.1.5 :001 > 123
Integer found!
=> 123
2.1.5 :002 > "string"
=> "string"

ruby's =~ operator return values?

def starts_with_consonant?(s)
if /^(a|e|i|o|u).*/i =~ s
true
else
false
end
end
# prints out true
puts starts_with_consonant?('aa')
# prints out false
puts starts_with_consonant?('da')
If I change the code just to
def starts_with_consonant?(s)
/^(a|e|i|o|u).*/i =~ s
end
Is that same functionality because
puts starts_with_consonant?('aa').inspect
prints out 0 (Shouldn't it be 1?)
puts starts_with_consonant?('da').inspect
prints out nil
# both print out 0
puts starts_with_consonant?('aa').to_i
puts starts_with_consonant?('da').to_i
What gives?
The =~ operator returns the first match index if the String and Regexp match, otherwise nil is returned:
'foo' =~ /bar/ # => nil
'foo bar' =~ /bar/ # => 4
Your first method, with the if/else statement, is treating the result of the =~ check as "truthy value or not?". If the match is found in the string, it returns the index (in your case, 0) or if it is not found, it returns nil.
0 is a truthy value; nil is not.
Therefore, even though it's returning the same result in each of your methods containing the /.../ =~ s expression, you get different return values out of the methods, depending on what you do with that result.
In the if/else statement, you get true when it's the truthy value of 0, and false when it's the non-truthy value of nil.
In the bare return statement, you get the plain return values of 0 and nil.
well the #=~ method actually returns the index where the first match occurs.
You can't do nil.to_i because that produces zero.
[6] pry(main)> nil.to_i
=> 0
puts starts_with_consonant?('aa').inspect
prints out 0 (Shouldn't it be 1?)
No, it should be 0. Strings are zero-indexed, the pattern has been found on the zeroth position. 0 is a truthy value, triggering the if clause if evaluated there. 'da' =~ /a/ would return 1, since a is the 1st character in the string (d being 0th).
puts starts_with_consonant?('da').inspect
prints out nil
There is no position that matches the pattern, so the return value is nil, a falsy value, which triggers the else clause if evaluated as an if condition.
# both print out 0
puts starts_with_consonant?('aa').to_i
puts starts_with_consonant?('da').to_i
Because both 0.to_i and nil.to_i result in 0.
Your getting back truthy. You can't print it but you can use it, e.g.
2.0.0-p247 :007 > if "aaaabcd" =~ /a/ then puts "true" end
true
=> nil
2.0.0-p247 :008 > if "aaaabcd" =~ /aaa/ then puts "true" end
true
=> nil
2.0.0-p247 :009 > if "aaaabcd" =~ /z/ then puts "true" end
=> nil
Similarly you can set a variable based on the evaluation, i.e.
2.0.0-p247 :013 > if "aaaabcd" =~ /a/ then b=1 end
=> 1
2.0.0-p247 :014 > if "aaaabcd" =~ /aaa/ then b=1 end
=> 1
2.0.0-p247 :015 > if "aaaabcd" =~ /zzz/ then b=1 end
=> nil

undefined method (NoMethodError) ruby

I keep getting the following error message:
text.rb:2:in `<main>': undefined method `choices' for main:Object (NoMethodError)
But I can't seem to understand why my method is "undefined":
puts "Select [1] [2] [3] or [q] to quit"; users_choice = gets.chomp
choices(users_choice)
def choices (choice)
while choice != 'q'
case choice
when '1'
puts "you chose one!"
when '2'
puts "you chose two!"
when '3'
puts "you chose three!"
end
end
end
This is because you are calling method choices, before defining it. Write the code as below:
puts "Select [1] [2] [3] or [q] to quit"
users_choice = gets.chomp
def choices (choice)
while choice != 'q'
case choice
when '1'
break puts "you chose one!"
when '2'
break puts "you chose two!"
when '3'
break puts "you chose three!"
end
end
end
choices(users_choice)
I used break, to exit from the while loop. Otherwise it will create an infinite loop.
def main
puts "Select [1] [2] [3] or [q] to quit"; users_choice = gets.chomp
choices(users_choice)
end
def choices (choice)
while choice != 'q'
case choice
when '1'
puts "you chose one!"
break
when '2'
puts "you chose two!"
break
when '3'
puts "you chose three!"
break
end
end
end
main
The method only needs to be called prior to being executed. Here I wrap the definition in the main method, but only call main after the definition of choices().
I was getting the same error running Ruby in Eclipse working out the App Academy practice exercises. I forgot to add "object." to the supplied test cases. The following syntax works:
#!/usr/bin/ruby
class Prime
# Write a method that takes in an integer (greater than one) and
# returns true if it is prime; otherwise return false.
#
# You may want to use the `%` modulo operation. `5 % 2` returns the
# remainder when dividing 5 by 2; therefore, `5 % 2 == 1`. In the case
# of `6 % 2`, since 2 evenly divides 6 with no remainder, `6 % 2 == 0`.
# More generally, if `m` and `n` are integers, `m % n == 0` if and only
# if `n` divides `m` evenly.
#
# You would not be expected to already know about modulo for the
# challenge.
#
# Difficulty: medium.
def primer(number)
if number < 2
return false
end
i = 10
while i > 1
if number > i && number != i
if number % i == 0
return false
end
end
i -= 1
end
return true
end
end
object = Prime. new
# These are tests to check that your code is working. After writing
# your solution, they should all print true.
puts("\nTests for #primer")
puts("===============================================")
puts('primer(2) == true: ' + (object.primer(2) == true).to_s)
puts('primer(3) == true: ' + (object.primer(3) == true).to_s)
puts('primer(4) == false: ' + (object.primer(4) == false).to_s)
puts('primer(9) == false: ' + (object.primer(9) == false).to_s)
puts("===============================================")

Resources