is this a valid ruby syntax? - ruby

if step.include? "apples" or "banana" or "cheese"
say "yay"
end

Several issues with your code.
step.include? "apples" or "banana" or "cheese"
This expression evaluates to:
step.include?("apples") or ("banana") or ("cheese")
Because Ruby treats all values other than false and nil as true, this expression will always be true. (In this case, the value "banana" will short-circuit the expression and cause it to evaluate as true, even if the value of step does not contain any of these three.)
Your intent was:
step.include? "apples" or step.include? "banana" or step.include? "cheese"
However, this is inefficient. Also it uses or instead of ||, which has a different operator precedence, and usually shouldn't be used in if conditionals.
Normal or usage:
do_something or raise "Something went wrong."
A better way of writing this would have been:
step =~ /apples|banana|cheese/
This uses a regular expression, which you're going to use a lot in Ruby.
And finally, there is no say method in Ruby unless you define one. Normally you would print something by calling puts.
So the final code looks like:
if step =~ /apples|banana|cheese/
puts "yay"
end

The last two terms appear to Ruby as true, rather than having anything to do with the include? phrase.
Assuming that step is a string...
step = "some long string with cheese in the middle"
you could write something like this.
puts "yay" if step.match(/apples|banana|cheese/)

Here's a way to call step.include? on each of the arguments until one of them returns true:
if ["apples", "banana", "cheese"].any? {|x| step.include? x}

It's definitely not what you appear to be wanting. The include? method takes in a String, which is not what "apples" or "banana" or "cheese" produces. Try this instead:
puts "yay" if ["apples", "banana", "cheese"].include?(step)
But it's unclear from the context what step is supposed to be. If it's just the single word, then this is fine. If it can be a whole sentence, try joel.neely's answer.

The closest thing to that syntax that would do what you appear to want would be something like:
if ["apples", "banana", "cheese"].include?(step)
puts "yay"
end
But one of the other suggestions using a regex would be more concise and readable.

Assuming step is an Array or a Set or something else that supports set intersection with the & operator, I think the following code is the most idiomatic:
unless (step & ["apples","banana","cheese"]).empty?
puts 'yay'
end

I'll add some parentheses for you:
if (step.include? "apples") or ("banana") or ("cheese")
say "yay"
end
(That would be why it's always saying "yay" -- because the expression will always be true.)

Just to add another side to this...
If step is an Array (as calling include? seems to suggest) then maybe the code should be:
if (step - %w{apples banana cheese}) != step
puts 'yay'
end

Related

What's the major difference between if statements and unless statements?

I am new to programming and I don't understand what the difference is. I am coding in Ruby.
if should be obvious: execute a block of code if the condition is true.
unless is the opposite: execute a block of code if the condition is false.
http://www.codecademy.com/glossary/ruby/if-unless-elsif-and-else
unless is equal to if not
for example:
a= false
unless a
puts "hello"
end
=> hello
if not a
puts "hello"
end
=> hello
One of the goals of Ruby language is to become more closer to the real English. And keywords if and unless are really good examples of that. Look at this:
if animal.can_speak?
animal.say 'Woof!'
end
# moreover, it can be transformed in one-line, which looks pretty awesome:
animal.say 'Woof!' if animal.can_speak?
unless is an opposite of the if and instead of writing:
if not animal.can_speak?
puts "This animal can't speak"
end
we can use unless, that usually considered as more natural way:
unless animal.can_speak?
puts "This animal can't speak"
end
# it also has one-line approach:
puts "..." unless animal.can_speak?

Multiple in-place substitutions in one line

What is the most idiomatic way to do multiple in-place substitutions on a string when none of the patterns being replaced are guaranteed to have a match?
For instance, say I have an array of strings and I want to replace "sad" with "happy" and "goodbye" with "hello" in each one:
a = ["I am sad", "goodbye for now"]
# This will work:
a.map! do |s|
s = s.gsub(/sad/,"happy").gsub(/goodbye/,"hello")
end
# So will this:
a.each do |s|
s.gsub!(/sad/,"happy")
s.gsub!(/goodbye/,"hello")
end
# This will fail when s does not match /sad/:
a.each do |s|
s.gsub!(/sad/,"happy").gsub!(/goodbye/,"hello")
end
The first option seems a little bit silly, since logically I'm trying to do an in-place substitution rather than a re-assignment. The second option is okay, but my aesthetic sense tells me that it seems wrong to be required to turn the substitution into two sequential statements, particularly in cases when only one or the other substitution is expected to be successful (which, ironically, is exactly the case that causes the third version, which looks "right" to me, to fail). Also, it's probably wrong to use each destructively as I'm doing here, but if I used map! instead, I'd need to add s as the final line in the block to ensure I don't accidentally make nil entries when substitution fails, which seems almost sillier than the first option.
I'm guessing the reason the (g)sub! methods return nil when no substitution is done is because that makes them convenient for use in logical constructs, which is admittedly a very good reason (especially since the non-destructive versions obviously must return "true" values no matter what).
So...I know this is really very little more than a minor aesthetic quibble, but is there a better way than the two (working) ways I've shown? If not, is there any reason to prefer one over the other (beyond my intuitive aesthetic preference for the second version)?
First you need to create a replacement_hash as below :
replacement_hash = { "sad" => "happy", "goodbye" => "hello"}
a = ["I am sad", "goodbye for now"]
Regexp.union(replacement_hash.keys) # => /sad|goodbye/
a.map { |s| s.gsub(Regexp.union(replacement_hash.keys), replacement_hash) }
# => ["I am happy", "hello for now"]
If in-place replacement needed, do as below :-
a.each { |s| s.gsub!(Regexp.union(replacement_hash.keys), replacement_hash) }

What is wrong with my conditional statement? I'm trying to pull the vowels out

I'm able to get this code to work if I use several if/elsif statements but would like to keep the code neat. Please let me know what is wrong with this code. I was expecting to see an array with ["e"] but returns []
def pull_vowels(str)
letters=str.split(//)
vowels=[]
0.upto(letters.count-1) {|idx|
vowels<<letters[idx] if letters[idx]==("a"||"e"||"i"||"o"||"u")
}
vowels
end
pull_vowels("test")
I guess it's ruby.
Interpreter is not clever enough to understand your intention in if letters[idx]==("a"||"e"||"i"||"o"||"u").
It actually first evals ("a"||"e"||"i"||"o"||"u") to "a", and then reserves "a" only.
You have to specify each case like if letters[idx]=="a" or letters[idx]=="e" or ...
Another solution is to use regular expression, like if letters[idx] =~ /[aeiou]/
In ruby, you can implement all this more elegently, say
def pull_vowels(str)
str.scan /[aeiou]/
end

Can't understand "unless" keyword in Ruby

I'm not a native English speaker. I know it sounds stupid nonetheless. I write in Python & C. But I can't quite understand how unless works.
Is it healthy to think of it from a logical standpoint? Eg, consider the if keyword: if condition. If condition is true, the code runs. What's the logical explanation for unless?
Is there any other way to think of it?
unless x is equivalent to if !x
Ruby unless modifier:
Syntax: code unless conditional
Executes code if conditional is false.
Example:
$var = 1
print "1 -- Value is set\n" if $var
print "2 -- Value is set\n" unless $var
$var = false
print "3 -- Value is set\n" unless $var
This will produce following result:
1 -- Value is set
3 -- Value is set
The easiest way is: unless is an opposite of if. It works in the same places (I think) as if:
foo = nil
puts "This will not show" if foo
puts "But this will" unless foo
if foo then
puts "This will not show"
end
unless foo
puts "But this will"
end
It looks nicer in the code if you write unless foo instead of if !foo - but that is only my opinion. In the longer form, you can even use else, but please, do not.
Here is a set of rules to follow to make the code more readable.
The way i think of it is to say:
"The block of code is going to be executed, unless the condition is true"
unless <condition>
<code>
end
hungry = true
unless hungry
puts "I'm writing Ruby programs!"
else
puts "Time to eat!"
end
This is the easy way to understand

Why does a switch statement perform equality testing differently from an if statement?

Why does the if statement work in the example below while the switch statement does not.
working:
if ''.class == String
puts "yep, that's a string"
end
not working:
case ''.class
when String
puts "yep, that's a string, but this case is never triggered"
end
In the trivial example above, the switch statement is overkill, but there are obviously situations where a switch statement would be DRYer than chained elsifs
Actually, ruby's "case" makes the comparaison with ===
So your example is equivalent to :
if ''.class === String
puts "yep, that's a string"
end
This is because the case statement doesn't use the == operator, it uses the === operator (sometimes called the case equality operator). What this does varies depending on what's on the left side of the operator. So, if you were to transform case statement like this:
case "Some string"
when String
puts "It's a string!"
else
puts "It's not a string!"
end
Into an if statement, it would become this:
if String === "Some string"
puts "It's a string!"
else
puts "It's not a string!"
end
Note that Ruby does this backwards from how you'd expect, it does String === "Some string". This is because what you really want to do is call Class#=== here, and not String#===. What the === operator does for any object is really up to the class. In the case of Class#===, it's roughly equivalent to calling "Some string".is_a?(String). But if you were to do "a" === "b", the String#=== method is roughly equivalent to String#==.
It can get confusing, but the operator's usage is largely idiomatic. In other words, the "class object in a when statement" idiom means to test if the case object is of that class. I've written an article on this that explains it a bit more, you can read it here.
The quick and simple answer is that case uses === (3 equals) and not two.
$ irb
if ''.class == String
puts "yep, that's a string"
end
yep, that's a string
=> nil
if ''.class === String
puts "yep, that's a string"
end
=> nil
As others have said, case equality in Ruby works a bit differently than you might expect, so you can just do
case foo
when String # that is, when String === foo, more or less when foo.class == String
do something
end
But generally, you shouldn't. If you're explicitly testing class names, then (usually) your OO design is flawed -- in most cases, you should try to use polymorphism instead. In other words, instead of
if x.class == String
x.process_string
else
x.process_non_string
end
you should simply have x.process, and then define process differently for String and other classes. Cleaner, less code, doesn't force the caller to know the class of the called object.

Resources