Why are exclamation marks used in Ruby methods?
In general, methods that end in !
indicate that the method will modify the object it's called on. Ruby calls these as "dangerous methods" because they change state that someone else might have a reference to. Here's a simple example for strings:
foo = "A STRING" # a string called foo
foo.downcase! # modifies foo itself
puts foo # prints modified foo
This will output:
a string
In the standard libraries, there are a lot of places you'll see pairs of similarly named methods, one with the !
and one without. The ones without are called "safe methods", and they return a copy of the original with changes applied to the copy, with the callee unchanged. Here's the same example without the !
:
foo = "A STRING" # a string called foo
bar = foo.downcase # doesn't modify foo; returns a modified string
puts foo # prints unchanged foo
puts bar # prints newly created bar
This outputs:
A STRING
a string
Keep in mind this is just a convention, but a lot of Ruby classes follow it. It also helps you keep track of what's getting modified in your code.
What is the point of the method method in Ruby?
A Method
object provides for all sorts of introspection and metaprogramming, including:
- Getting the arity or parameters for the method
- Getting the source code location for the method, which is useful in debugging or when writing tools that interact or inspect the source of the application that's running
- Getting the receiver of the method
How and what you use those powers for is up to you.
For Cary, below:
"cat".method(:count).receiver
# => "cat"
What is the purpose of ! and ? at the end of method names?
It's "just sugarcoating" for readability, but they do have common meanings:
- Methods ending in
!
perform some permanent or potentially dangerous change; for example:Enumerable#sort
returns a sorted version of the object whileEnumerable#sort!
sorts it in place.- In Rails,
ActiveRecord::Base#save
returns false if saving failed, whileActiveRecord::Base#save!
raises an exception. Kernel::exit
causes a script to exit, whileKernel::exit!
does so immediately, bypassing any exit handlers.
- Methods ending in
?
return a boolean, which makes the code flow even more intuitively like a sentence —if number.zero?
reads like "if the number is zero", butif number.zero
just looks weird.
In your example, name.reverse
evaluates to a reversed string, but only after the name.reverse!
line does the name
variable actually contain the reversed name. name.is_binary_data?
looks like "is name
binary data?".
What does ! mean at the end of a Ruby method definition?
Ruby doesn't treat the !
as a special character at the end of a method name. By convention, methods ending in !
have some sort of side-effect or other issue that the method author is trying to draw attention to. Examples are methods that do in-place changes, or might throw an exception, or proceed with an action despite warnings.
For example, here's how String#upcase!
compares to String#upcase
:
1.9.3p392 :004 > foo = "whatever"
=> "whatever"
1.9.3p392 :005 > foo.upcase
=> "WHATEVER"
1.9.3p392 :006 > foo
=> "whatever"
1.9.3p392 :007 > foo.upcase!
=> "WHATEVER"
1.9.3p392 :008 > foo
=> "WHATEVER"
ActiveRecord makes extensive use of bang-methods for things like save!
, which raises an exception on failure (vs save
, which returns true/false but doesn't raise an exception).
It's a "heads up!" flag, but there's nothing that enforces this. You could end all your methods in !
, if you wanted to confuse and/or scare people.
Ruby method for +=
The +=
operator is not associated to any method, it is just syntactic sugar, when you write a += b
the Ruby interpreter transform it to a = a + b
, the same is for a.b += c
that is transformed to a.b = a.b + c
. Thus you just have to define the methods x=
and x
as you need:
class Plane
def initialize
@moved = 0
@x = 0
end
attr_reader :x
def x=(x)
@x = x
@moved += 1
end
def to_s
"moved #{@moved} times, current x is #{@x}"
end
end
plane = Plane.new
plane.x += 5
plane.x += 10
puts plane.to_s
# => moved 2 times, current x is 15
Is there a method for in place modification on Object in ruby?
This is impossible. A method that modifies any object can only know how to manipulate the state which is common to all objects, and that is none.
A method that can replace any object in Ruby with a new one is impossible since object references cannot change their class in Ruby.
It sounds like you are a Smalltalk programmer, and you are looking for an equivalent to become:
? That is impossible in Ruby.
What is the proper way to add a method to a built-in class in ruby?
tenebrousedge there was probably hinting at refinements.
Or, rather, not patching String
at all. More often than not, monkeypatching creates more problems than it solves. What if String already knew alpha?
and it did something different?
For example, future versions of ruby might add String#alpha?
that will handle unicode properly
'新幹線'.alpha? # => true
and your code, as it is, would overwrite this built-in functionality with an inferior version. Now your app is breaking in all kinds of places, because stdlib/rails assumes the new behaviour. Chaos!
This is to say: avoid monkeypatching whenever possible. And when you can't avoid, use refinements.
Ruby | Problem with method for build pyramids
Basically you need to pass the variable espace
to your method full_pyramid
, so you just need a small change.
Since ask_etages
asks the user for an input (side note: use puts
instead of print
) then returns that value as integer you need to pass it to full_pyramid
.
Do to so just define the method as:
def full_pyramid(etages)
espace = etages - 1
carre = 1
etages.times do
espace.times do
print " "
end
espace -= 1
carre.times do
print "#"
end
carre += 2
puts " "
end
end
Then define perform
as:
def perform
full_pyramid(ask_etages)
end
How to return a splat from a method in Ruby
You cannot return a "splat" from Ruby. But you can return an array and then splat it yourself:
def args
[1, 2, 3]
end
x, y, z = args
# x == 1
# y == 2
# z == 3
x, *y = args
# x == 1
# y == [2, 3]
Of course, this works on any array, so really there is no need for monkey patching a to_args
method into Array
- it's all about how the calling concern is using the splat operator:
arr = [1, 2, 3]
x, y, z = arr
x, *y = arr
*x, y = arr
Same mechanism works with block arguments:
arr = [1, 2, 3]
arr.tap {|x, *y| y == [2, 3]}
Even more advanced usage:
arr = [1, [2, 3]]
x, (y, z) = arr
Related Topics
How to Inspect What Is the Default Value for Optional Parameter in Ruby's Method
Authlogic and Multiple Sessions for the Same User
Ruby Operator Method Calls VS. Normal Method Calls
Rails 5 Db Migration: How to Fix Activerecord::Concurrentmigrationerror
Slicing Params Hash for Specific Values
How to Install Rails with Jruby
Are There Primitive Types in Ruby
Mailchimp API Not Replacing Mc:Edit Content Sections (Using Ruby Library)
If 'Main' Is an Instance of 'Object', Why Can't I Call It
What Does +@ Mean as a Method in Ruby
Differencebetween Ruby's 'Open-Uri' and 'Net:Http' Gems
Installing Rmagick Gem -- Can't Find Magickwand.H
How to Model a Mutual Friendship in Rails
Why am I Getting This Passenger Error Could Not Find Rake-0.9.2.2 in Any of the Sources
Rmagick - How to Find Out the Pixel Dimension of an Image