What does to_s with a colon do? [duplicate] - ruby

This question already has answers here:
How do I use the conditional operator (? :) in Ruby?
(7 answers)
Closed 1 year ago.
I am just wondering what happens to an object when to_s is applied to it with a colon? It is supposed to turn a single letter string into a symbol for a card game. Could someone explain if that is correct? Thanks! Here's an example:
def to_s
revealed? ? value.to_s : " "
end

Are you referring to the ternary operator?
It's the same as:
if revealed?
value.to_s
else
" "
end

This is the ternary operator.
condition ? expression-to-evaluate-if-true : expression-to-evaluate-if-false
Your example is equivalent to:
def to_s
if revealed?
value.to_s
else
" "
end
end
In other words, the ? : construct has nothing specifically to do with to_s.

Related

Why doesn't my ruby method call work? (yield) [duplicate]

This question already has answers here:
Passing block into a method - Ruby [duplicate]
(2 answers)
Closed 2 years ago.
I can't figure out why I get this error message when I run my file on the console: no block given (yield) (LocalJumpError)
Here my code:
def block_splitter(array)
array.partition { |item| yield(item) }
end
beatles = ["John", "Paul", "Ringo", "George"]
puts block_splitter(beatles) do |beatle|
beatle.start_with?("P")
end
Thanks for your help!
It's a whitespace issue. Your problem is in this line:
puts block_splitter(beatles) do |beatle|
# ...
end
The above code is being interpreted like this:
puts(block_splitter(beatles)) do |beatle|
# ...
end
I.e. the ruby interpreter thinks that the block is being passed to the puts method, not the block_splitter method.
By assigning a variable and printing the result, you'll see that this works as expected:
result = block_splitter(beatles) do |beatle|
beatle.start_with?("P")
end
puts result
Or, you can define this as a 1-liner, and the ruby interpreter handles it like you expected:
puts block_splitter(beatles) { |beatle| beatle.start_with?("P") }
Or, you could wrap it in extra brackets:
puts(block_splitter(beatles) do |beatle|
beatle.start_with?("P")
end)
So there is a problem with missing parentheses. Ruby interpreter allow not to use those, but when You use nested method calls It's better (and sometimes necessary) to use them. To fix it You can do something like this
puts(block_splitter(beatles) do |beatle|
beatle.start_with?("P")
end)
Or even better
puts(block_splitter(beatles) {|beatle| beatle.start_with?("P")})

How should I setup this if and else statement? [duplicate]

This question already has answers here:
Array that alphabetizes and alternates between all caps
(5 answers)
Closed 7 years ago.
Without changing any of the other code- What can I put into my if else statement to make array 0, 2, 4 show up as all capital letters? I can't figure out how to assign this within the if and else statement.
test = []
puts "Please type 5 different words when you're ready-"
5.times do
test << gets.chomp
end
test.sort.each do |user|
if #what could I put in this statement for all capital letters on [0,2,4]?
user.upcase
else #.downcase isn't needed, if its simpler to remove it that is fine
user.downcase
end
end
I think what you need to do is change the each loop to each_with_index. The each_with_index loop should get what you need.
test.sort.each_with_index do |user, index|
if ([0,2,4]include? index)
user.upcase
else
user.downcase
end
end
If the array is going to expand, you could use the #even? method on the index as the check in the if statement like so.
test.sort.each_with_index do |user, index|
if (index.even?)
user.upcase
else
user.downcase
end
end
If you can't change the type of loop then you could use the #index method on the array, to tell you where the user is in the test array like so
test.sort.each do |user|
if ([0,2,4].include? (test.sort.index(user)))
user.upcase
else
user.downcase
end
end
Why without changing any of the other code? Just do this, no one will care:
puts "Please type 5 different words when you're ready-"
5.times.map { |i| i.even? ? gets.chomp.downcase : gets.chomp.upcase }
The times loop autoindexes for this reason, and the ternary operator (?:) is built for this case.

What does "||=" mean in Ruby? [duplicate]

This question already has answers here:
What does ||= (or-equals) mean in Ruby?
(23 answers)
Closed 7 years ago.
I'm still pretty green when it comes to Ruby and am trying to figure out what this is doing:
command_windows.each {|window| window.hidden ||= window.open? }
The command_windows variable appears to be an array of objects. If someone could explain to me what this line of code means, particularly what the ||= symbol is I would appreciate it.
foo ||= "bar" is the equivalent of doing foo || foo = "bar".
As Mischa explained, it checks for a falsy value before assigning.
In your case, you could think of it as:
command_windows.each {|window| window.hidden || window.hidden = window.open? }
which is another way of saying
command_windows.each {|window| window.hidden = window.open? unless window.hidden }
The ||= operator is used to assign new value to variable. If something was assigned to it before it won't work. It is usually used in hashes, so you don't have to check, if something is already assigned.

Function overloading in Ruby [duplicate]

This question already has answers here:
Why doesn't ruby support method overloading?
(9 answers)
Closed 7 years ago.
I have this piece of code in Ruby.
class Superheros
class<<self
def foo1(param1)
print "foo1 got executed\n"
end
def foo1
print "foo1 without param got executed\n"
end
def foo3(param1,param2)
print "foo3 got executed\n"
end
end
end
print Superheros.foo3(2,3)
print Superheros.foo1
print Superheros.foo1
print Superheros.foo1(5)
I get the error in Superheros.foo1(5) . But i already have the function foo1(param1) to match it with, but it gives me an error
`foo1': wrong number of arguments (1 for 0) (ArgumentError)
Why is that?
PS: I found out if i remove the function name without the parameter,
the Superheros.foo1(5) works just fine.
Ruby doesn't support method overloading. In your code, your second definition of foo1 replaced the first. That's why you get an error when you try to pass arguments, the method that accepted arguments is gone.
There is a question on SO about this topic here, with some good explanations.
Maybe you could use variable arguments:
def foo1(*args)
case args.length
when 1
puts "Function A"
when 2
puts "Function B"
else
puts "Called with #{args.length} arguments"
end
end

what does #{ do in Ruby? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Meaning of #{ } in Ruby?
I know it is used for meta-programming, and I'm having a hard time trying to wrap my mind about what this operator is doing in the following example:
class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s # make sure it's a string
attr_reader attr_name
attr_reader attr_name+"_history"
class_eval %Q"
def #{attr_name}=(value)
if !defined? ##{attr_name}_history
##{attr_name}_history = [##{attr_name}]
end
##{attr_name} = value
##{attr_name}_history << value
end
"
end
end
class Foo
attr_accessor_with_history :bar
end
In general terms, #{...} evaluates whatever's inside of it and returns that, converted to a string with to_s. This makes it a lot easier to combine several things in a single string.
A typical example:
"There are #{n} car#{n == 1 ? '' : 's'} in the #{s}"
This is equivalent to:
"There are " + n.to_s + " car" + (n == 1 ? '' : 's').to_s + " in the " + s.to+_s
It's important to remember that the contents of the #{...} interpolation is actually a block of Ruby code and the result of it will be converted to a string before being combined.
That example of meta programming is awfully lazy as instance_variable_get and instance_variable_set could've been used and eval could've been avoided. Most of the time you'll see string interpolation used to create strings, not methods or classes.
There's a more robust formatter with the String#% method:
"There are %d car%s in the %s" % [ n, (n == 1 ? '' : 's'), s ]
This can be used to add a precise number of decimal places, pad strings with spaces, and other useful things.
#{var} does variable substitution in Ruby. For example:
var = "Hello, my name is #{name}"
The code you've posted is generating a string with the code for an accessor method for the attr_name you've passed in.
It's not doing much really :D. All the red text is basically just a string. The "bla #{var} bla" part is just a nicer way of writing "bla " + var + " bla". Try it yourself in irb:
a = 10
puts "The Joker stole #{a} pies."
what it does is called variable interpolation.
name = "Bond"
p "The name is #{name}. James #{name}."
will output,
> "The name is Bond. James Bond."

Resources