Ruby beginner i'm a little confused [duplicate] - ruby

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.

Related

Ruby Splatted Array

Create a method called introduction that accepts a person's age, gender and any number of names, then returns a String that introduces that person by combining all of these values to create a message acceptable to the tests.
def introduction(age, gender, *names)
"Meet #{names.join(' ')}, who's #{age} and #{gender}"
end
For the .join method. Why do I need to add a string with a space (' ')?
Thanks in advance
The documentation of Ruby's Array#join method can be found here:
http://ruby-doc.org/core/Array.html#method-i-join
The string ' ' is a string with a single space in it. That string is supplied as the separator argument to Array#join. If you left out that argument, then the names would not have any spaces between them, and it would look bad:
Meet DavidGrayson, who's 123 and male.
But if you include the space, it should look like this:
Meet David Grayson, who's 123 and male.
You should be able to answer a question like that yourself by running the code in IRB or some other Ruby environment and seeing how it behaves. Experimentation is a great way to start understanding something.

Ruby variable name with double underscores

Sometimes I see variable names with double underscore in the beginning and the end. For example:
Article.__elasticsearch__
Is there some naming convention related to double underscores in Ruby variable names?
An initial underscore or double underscore basically indicates
"special/avoid overwrite" --meaning it's meant to reduce the
likelihood that someone else might define a method/attribute of the
same name. The most common occurrence is __send__.
From Ruby Forum
The author of the ElasticSearch gem made the wrong call IMO. At the end of the thread, Avdi Grimm, who is well-known in the Ruby community, disagrees with the OP.
There's a reason you hadn't seen it yet and that it looks odd to you. It's because it's unidiomatic.

.downcase! syntax shorthand

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.

ALL CAPS to Normal case

I'm trying to find an elegant solution on how to convert something like this
ALL CAPS TEXT. "WHY ANYONE WOULD USE IT?" THIS IS RIDICULOUS! HELP.
...to regular-case. I could more or less find all sentence-starting characters with:
(?<=^|(\. \"?)|(! ))[A-Z] #this regex sure should be more complex
but (standard) Ruby neither allows lookbehinds, nor it is possible to apply .capitalize to, say, gsub replacements. I wish I could do this:
"mytext".gsub(/my(regex)/, '\1'.capitalize)
but the current working solution would be to
"mytext".split(/\. /).each {|x| p x.capitalize } #but this solution sucks
First of all, notice that what you are trying to do will only be an approximation.
You cannot correctly tell where the sentence boundaries are. You can approximate it as The beginning of the entire string or right after a period, question mark, or exclamation mark followed by spaces. But then, you will incorrectly capitalize "economy" in "U.S. economy".
You cannot correctly tell which words should be capitalized. For example, "John" will be "john".
You may want to do some natural language processing to give you a close-to-correct result in many cases, but these methods are only probablistically correct. You will never get a perfect result.
Understanding these limitations, you might want to do:
mytext.gsub(/.*?(?:[.?!]\s+|\z)/, &:capitalize)

Ruby Array#puts not using overridden implementation?

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.

Resources