Can someone explain what the difference is between the two pieces of code below? Both feature an ! at the end. Is the first version just the shorthand?
print "Who are you?"
user_input = gets.chomp.downcase!
print "Who are you?"
user_input = gets.chomp
user_input.downcase!
Edit: Having an exclamation point (aka "bang") at the end of a method name in ruby means "handle with care". From Matz himself:
The bang (!) does not mean "destructive" nor lack of it mean non
destructive either. The bang sign means "the bang version is more
dangerous than its non bang counterpart; handle with care". Since
Ruby has a lot of "destructive" methods, if bang signs follow your
opinion, every Ruby program would be full of bangs, thus ugly.
(For the full thread, see #sawa's link in the comments.)
For the method in question, downcase is making a copy of the given string, modifying that, and returning that copy as a result. Whereas downcase! modifies the string itself.
In the first case, you're modifying the variable stored in gets.chomp, in the second you're modifying user_input.
Note that if you call user_input.downcase on the last line (instead of user_input.downcase!) it won't actually change user_input, it just returns a copy of the string and makes the copy lowercase.
Related
My code is about a robot who has 3 posible answers (it depends on what you put in the message)
So, inside this posible answers, one depends if the input it's a question, and to prove it, i think it has to identify the "?" symbol on the string.
May i have to use the "match" method or includes?
This code it's gonna be include in a loop, that may answer in 3 possible ways.
Example:
puts "whats your meal today?"
answer = gets.chomp
answer.includes? "?"
or
answer.match('?')
Take a look at String#end_with? I think that is what you should use.
Use String#match? Instead
String#chomp will only remove OS-specific newlines from a String, but neither String#chomp nor String#end_with? will handle certain edge cases like multi-line matches or strings where you have whitespace characters at the end. Instead, use a regular expression with String#match?. For example:
print "Enter a meal: "
answer = gets.chomp
answer.match? /\?\s*\z/m
The Regexp literal /\?\s*\z/m will return true value if the (possibly multi-line) String in your answer contains:
a literal question mark (which is why it's escaped)...
followed by zero or more whitespace characters...
anchored to the end-of-string with or without newline characters, e.g. \n or \r\n, although those will generally have been removed by #chomp already.
This will be more robust than your current solution, and will handle a wider variety of inputs while being more accurate at finding strings that end with a question mark without regard to trailing whitespace or line endings.
This question already has answers here:
Why are exclamation marks used in Ruby methods?
(12 answers)
Closed 6 years ago.
I would like to know what the difference is between these two examples:
my_name = gets.chomp
my_name.capitalize
and
my_name = gets.chomp
my_name.capitalize!
The difference is
my_name.capitalize
returns a capitalized version of my_name without affecting the object my_name points to, while
my_name.capitalize!
still returns a capitalized version of my_name but my_name is changed too, so
my_name = "john"
puts my_name.capitalize # print 'John' but the value of my_name is 'john'
puts my_name.capitalize! # print 'John' and now the value of my_name is 'John'
From the Ruby capitalize docs:
capitalize
Returns a copy of str with the first character converted to uppercase
and the remainder to lowercase.
capitalize!
Modifies str by converting the first character to uppercase and the
remainder to lowercase. Returns nil if no changes are made.
I'm always so happy to see somebody getting into ruby!
The thing with ruby is that, even though it's a very friendly language, it assumes a lot of things without necessarily telling the newbies about it. They make lots of sense once you have a couple months under the belt with the language, but not before, so I understand your question.
First of all, the bang (!) is just part of the name itself. Ruby allows exclamation points and question marks as part of the method name just as any other character. Cool, right?
Why do people bother, though? Well, it's a convention. As a rule of thumb, an accepted explanation of why a method should have a bang sign is that the method does an invasive, destructive or mutating thing, that is, it destroys data, runs a transaction on the database, permanently changes data, etc.
It's not obligatory to name these kinds of methods like this, but it's a convention that's very well withheld in the Ruby community.
Programming Ruby says:
Methods that are "dangerous," or modify the receiver, might be named
with a trailing "!".
Hope this answers your question.
I saw two ways to use gets, a simple form:
print 'Insert your name: '
name = gets()
puts "Your name is #{name}"
and a form that drew my attention:
print 'Insert your name: '
STDOUT.flush
name = gets.chomp
puts "Your name is #{name}"
The second sample looks like perl in using the flush method of the default output stream. Perl makes explicit default output stream manipulating; the method flush is a mystery to me. It can behave different from what I'm inferring, and it uses chomp to remove the new line character.
What happens behind the scenes in the second form? What situation is it useful or necessary to use the second form?
"Flushing" the output ensures that it shows the printed message before it waits for your input; this may be just someone being certain unnecessarily, or it may be that on certain operating systems you need it. Alternatively you can use STDOUT.sync = true to force a flush after every output. (You may wonder, "Why wouldn't I always use this?" Well, if your code is outputting a lot of content, repeatedly flushing it may slow it down.)
chomp removes the newline from the end of the input. If you want the newline (the result of the user pressing "Enter" after typing their name) then don't chomp it.
Looking at some Github code I can see that STDOUT.flush is used mostly for server-side/multi-threaded jobs, and not in everyday use.
Generally speaking, when you want to accept input from the user, you'd want to use gets.chomp. Just remember, no matter what the user enters, Ruby will ALWAYS interprete that as a string.
To convert it to an integer, you need to call to_i, or to_f for a float. You don't need chomp in these cases, since to_i or to_f removes the "\n" automatically. There are a lot of subtle things going on implicitly as you'll see, and figuring them out is simply a matter of practice.
I've rarely seen someone use STDOUT.flush except in mutli-threading. Also it makes things confusing, defeating the whole purpose of writing elegant code.
I see people use the following code:
gets.chomp.to_i
or
gets.chomp.to_f
I don't understand why, when the result of those lines are always the same as when there is no chomp after gets.
Is gets.chomp.to_i really necessary, or is gets.to_i just enough?
From the documentation for String#to_i:
Returns the result of interpreting leading characters in str as an
integer base base (between 2 and 36). Extraneous characters past the
end of a valid number are ignored. If there is not a valid number at
the start of str, 0 is returned
String#to_f behaves the same way, excluding, of course, the base numbers.
Extraneous characters past the end of a valid number are ignored, this would include the newline. So there is no need to use chomp.
There is no need to use chomp method because:
String#chomp returns a new String with the given record separator removed from the end of str (if present). If $/ has not been changed from the default Ruby record separator, then chomp also removes carriage return characters (that is it will remove "\n", "\r", and "\r\n"). Here are some examples.
String#to_f returns the result of interpreting leading characters in str as a floating point number. Extraneous characters past the end of a valid number are ignored. If there is not a valid number at the start of str, 0.0 is returned. This method never raises an exception. Here are some examples for to_f.
It is my opinion that it works the same either way, so there is no need for the chomp after gets if you are going to immediately do to_i or to_f.
In practice, I have never seen an error raised or different behavior because of leaving chomp out of the line.
I find it is distracting, when I see it used in answers, and there is absolutely no need for it. It doesn't add to a "style", and it is, as #TheTinMan states, wasted CPU cycles.
I am using Ruby 1.8.6 for the following code:
# Create an array and override the #to_s on that object
thing = [1,2,3]
def thing.to_s
'one'
end
print "Using print: "
print thing
puts
puts "Using puts: "
puts thing
Output:
Using print: one
Using puts:
1
2
3
So thing is an Array and I have overridden thing#to_s. print seems to use my overriden implementation while puts does not. Why?
I have followed the source code of Kernel#puts and Kernel#print (which are C-implementations) and see that they are very different implementations. I want to know what might be the design-decision (if any) behind this?
By the way, if I create thing as an instance of another class I wrote (or as a Hash/String/other-classes I tried), both print and puts use the overridden implementation of to_s.
Oh boy ... This has already been the topic of a countless number of endless threads on the ruby-talk mailinglist, the ruby-core mailinglist and a gazillion of blogs.
The gist of it is that puts special cases Arrays. Why it special cases those, why it special cases only those (as opposed to, say, all Enumerables), why it special cases those (and not, say, print), nobody really knows. It is the way it is.
BTW, since you mentioned the POLS: the Ruby community has always made it very clear that the POLS only applies to matz. So, Ruby is about not surprising matz. If you or me or anybody else is surprised, that doesn't count.
From the Ruby Programming Language:
alt text http://ecx.images-amazon.com/images/I/41n-JSlBHkL._SL75_.jpg
Output streams are appendable, like strings and arrays are, and you can write values to them with the << operator. puts is one of the most common output methods. It converts each of its arguments to a string, and writes each one to the stream. If the string does not already end with a newline character, it adds one. If any of the arguments to puts is an array, the array is recursively expanded, and each element is printed on its own line as if it were passed directly as an argument to puts. The print method converts its arguments to strings, and outputs them to the stream. If the global field separator $, has been changed from its default value of nil, then that value is output between each of the arguments to print. If the output record separator $/ has been changed from its default value of nil, then that value is output after all arguments are printed.
As for design decisions, that I do not know.