What does ! mean at the end of a Ruby method definition? [duplicate] - ruby

This question already has answers here:
Why are exclamation marks used in Ruby methods?
(12 answers)
Closed 9 years ago.
I'm trying to learn Ruby by reading code, but I bumped into the following situation, which I cannot find in any of my tutorials/cheatsheets.
def foo!
# do bar
return bar
end
What is the point of "!" in a 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.

! is a "bang" method, which changes the receiver and is a convention in Ruby.
You can define a ! version which might work like a non-bang method, but then it would then mislead other programmers if they didn't look at your method definition.
bang method in turn returns nil when no changes made to the receiver.
Examples without ! - You can see that the source string has not been changed:
str = "hello"
p str.delete("l") #=> "heo"
p str #=> "hello"
Examples with ! - You can see that the source string has been changed:
str = "hello"
p str.delete!("l") #=> "heo"
p str #=> "heo"
NOTE: There are some non-bang version methods, which also can change the receiver object:
str = "hello"
p str.concat(" world") #=> "hello world"
p str #=> "hello world"

! is not a method definition but is an convention used when you declaring an method and this method will change the object.
1.9.3-p194 :004 > a="hello "
=> "hello "
1.9.3-p194 :005 > a.strip
=> "hello"
1.9.3-p194 :006 > a
=> "hello "
1.9.3-p194 :007 > a.strip!
=> "hello"
1.9.3-p194 :008 > a
=> "hello"

Related

Why a dangerous method doesn't work with a character element of String in Ruby?

When I apply the upcase! method I get:
a="hello"
a.upcase!
a # Shows "HELLO"
But in this other case:
b="hello"
b[0].upcase!
b[0] # Shows h
b # Shows hello
I don't understand why the upcase! applied to b[0] doesn't have any efect.
b[0] returns a new String every time. Check out the object id:
b = 'hello'
# => "hello"
b[0].object_id
# => 1640520
b[0].object_id
# => 25290780
b[0].object_id
# => 24940620
When you are selecting an individual character in a string, you're not referencing the specific character, you're calling a accessor/mutator function which performs the evaluation:
2.0.0-p643 :001 > hello = "ruby"
=> "ruby"
2.0.0-p643 :002 > hello[0] = "R"
=> "R"
2.0.0-p643 :003 > hello
=> "Ruby"
In the case when you run a dangerous method, the value is requested by the accessor, then it's manipulated and the new variable is updated, but because there is no longer a connection between the character and the string, it will not update the reference.
2.0.0-p643 :004 > hello = "ruby"
=> "ruby"
2.0.0-p643 :005 > hello[0].upcase!
=> "R"
2.0.0-p643 :006 > hello
=> "ruby"

Print memory address for Ruby array

irb> class A; end
=> nil
irb> a=A.new
=> "#<A:0x3094638>"
irb> a.inspect
=> "#<A:0x3094638>"
irb> b=[]
=> []
irb> b.inspect
=> "[]"
How to get memory address of an array object?
Use the method Object#object_id.
Returns an integer identifier for obj. The same number will be returned on all calls to id for a given object, and no two active objects will share an id. #object_id is a different concept from the :name notation, which returns the symbol id of name.
Example :-
Arup-iMac:arup_ruby $ irb
2.1.2 :001 > s = "I am a string"
=> "I am a string"
2.1.2 :002 > obj_id = s.object_id
=> 2156122060
2.1.2 :003 > ObjectSpace._id2ref obj_id
=> "I am a string"
2.1.2 :004 >

Javascript-style `apply` in Ruby?

For methods in Ruby, is there anything similar to javascript's apply?
That is, if some method were defined to take a few parameters, say, some_method(a, b, c) and I have an array of three items, can I call some_method.apply(the_context, my_array_of_three_items)?
EDIT: (to clear up some confusion):
I don't care so much about the context of the call, I just want to avoid this:
my_params = [1, 2, 3]
some_method(my_params[0], my_params[1], my_params[2])
instead, I'm curious to know if there is something like this
my_params = [1, 2, 3]
some_method.apply(my_params)
There are bindings which are closest counterpart of javascript context, and there are unbound methods which can be later bound to object to be called in it's scope.
Bindings must be earlier captured, and they allow evaluating code from string in it's context.
Unbinding method captured from any object with method extractor allows you to later bind it to an object (note that it must share enough of interface for method to work) and call it in it's scope.
Unless you want to hack some very low-level things in Ruby, I would discourage use of both of above in favor of object-oriented solution.
EDIT:
If you simply want to call method, while it's arguments are contained in array use splat operator:
a = [1, 2, 3]
method(*a)
You can invoke a method whose name is only known at run-time by the send method on Class.
Update
To pass the arguments as an array:
$ irb
2.0.0p195 :001 > class Foo
2.0.0p195 :002?> def bar( a, b, c)
2.0.0p195 :003?> puts "bar called with #{a} #{b} #{c}"
2.0.0p195 :004?> end
2.0.0p195 :005?> end
=> nil
2.0.0p195 :006 > foo = Foo.new
=> #<Foo:0x000000022206a8>
2.0.0p195 :007 > foo.bar( 1, 2, "fred" )
bar called with 1 2 fred
=> nil
2.0.0p195 :009 > foo.send( :bar, *[1, 2, "jane"] )
bar called with 1 2 jane
=> nil
2.0.0p195 :010 >

Ruby Symbol#to_proc leaks references in 1.9.2-p180?

Ok, this is my second attempt at debugging the memory issues with my Sinatra app. I believe I have it nailed down into simple sample code this time.
It seems when I filter an array through .map(&:some_method), it causes the items in that array to not get garbage collected. Running the equivalent .map{|x| x.some_method} is totally fine.
Demonstration: Given a simple sample class:
class C
def foo
"foo"
end
end
If I run the following in IRB, it gets collected normally:
ruby-1.9.2-p180 :001 > a = 10.times.map{C.new}
=> [...]
ruby-1.9.2-p180 :002 > b = a.map{|x| x.foo}
=> ["foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo"]
ruby-1.9.2-p180 :003 > ObjectSpace.each_object(C){}
=> 10
ruby-1.9.2-p180 :004 > a = nil
=> nil
ruby-1.9.2-p180 :005 > b = nil
=> nil
ruby-1.9.2-p180 :006 > GC.start
=> nil
ruby-1.9.2-p180 :007 > ObjectSpace.each_object(C){}
=> 0
So no references to C exist anymore. Good. But substituting map{|x| x.foo} with map(&:foo) (which is advertised as equivalent), it doesn't get collected:
ruby-1.9.2-p180 :001 > a = 10.times.map{C.new}
=> [...]
ruby-1.9.2-p180 :002 > b = a.map(&:foo)
=> ["foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo"]
ruby-1.9.2-p180 :003 > ObjectSpace.each_object(C){}
=> 10
ruby-1.9.2-p180 :004 > a = nil
=> nil
ruby-1.9.2-p180 :005 > b = nil
=> nil
ruby-1.9.2-p180 :006 > GC.start
=> nil
ruby-1.9.2-p180 :007 > ObjectSpace.each_object(C){}
=> 10
ruby-1.9.2-p180 :008 >
Is this a ruby bug? I'll try in more versions of ruby to be sure but this seems like an obvious issue. Anyone know what I'm doing wrong?
Edit:
I've tried this in 1.8.7-p352 and it doesn't have the issue. 1.9.3-preview1 does however still have the issue. Is a bug report in order or am I doing something wrong?
Edit2: formatting (why does putting four spaces before each line produce syntax highlighting while <pre> tags don't?)
As a.map(&:foo) should be the exact equivalent to a.map{|x| x.foo}, it seems like you really hit a bug in the Ruby code here. It cannot hurt to file a bug report on (http://redmine.ruby-lang.org/), the worst that can happen is that its being ignored. You can decrease the chances of that by providing a patch for the issue.
EDIT: I threw on my IRB and tried your code. I can reproduce the issue you describe on ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]. However, explicitely calling to_proc on the symbol does not suffer from the same problem:
irb(main):001:0> class C; def foo; end; end
=> nil
irb(main):002:0> a = 10.times.map { C.new }
=> [...]
irb(main):004:0> b = a.map(&:foo.to_proc)
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
irb(main):005:0> ObjectSpace.each_object(C){}
=> 10
irb(main):006:0> a = b = nil
=> nil
irb(main):007:0> GC.start
=> nil
irb(main):008:0> ObjectSpace.each_object(C){}
=> 0
It seems we are facing an issue with the implicit Symbol -> Proc conversion here. Maybe I will try to dive a bit into the Ruby source later. If so, I will keep you updated.
EDIT 2:
Simple workaround for the problem:
class Symbol
def to_proc
lambda { |x| x.send(self) }
end
end
class C
def foo; "foo"; end
end
a = 10.times.map { C.new }
b = a.map(&:foo)
p b
a = b = nil
GC.start
p ObjectSpace.each_object(C) {}
prints 0.

What is the difference between Ruby 1.8 and Ruby 1.9

I'm not clear on the differences between the "current" version of Ruby (1.8) and the "new" version (1.9). Is there an "easy" or a "simple" explanation of the differences and why it is so different?
Sam Ruby has a cool slideshow that outline the differences.
In the interest of bringing this information inline for easier reference, and in case the link goes dead in the abstract future, here's an overview of Sam's slides. The slideshow is less overwhelming to review, but having it all laid out in a list like this is also helpful.
Ruby 1.9 - Major Features
Performance
Threads/Fibers
Encoding/Unicode
gems is (mostly) built-in now
if statements do not introduce scope in Ruby.
What's changed?
Single character strings.
Ruby 1.9
irb(main):001:0> ?c
=> "c"
Ruby 1.8.6
irb(main):001:0> ?c
=> 99
String index.
Ruby 1.9
irb(main):001:0> "cat"[1]
=> "a"
Ruby 1.8.6
irb(main):001:0> "cat"[1]
=> 97
{"a","b"} No Longer Supported
Ruby 1.9
irb(main):002:0> {1,2}
SyntaxError: (irb):2: syntax error, unexpected ',', expecting tASSOC
Ruby 1.8.6
irb(main):001:0> {1,2}
=> {1=>2}
Action: Convert to {1 => 2}
Array.to_s Now Contains Punctuation
Ruby 1.9
irb(main):001:0> [1,2,3].to_s
=> "[1, 2, 3]"
Ruby 1.8.6
irb(main):001:0> [1,2,3].to_s
=> "123"
Action: Use .join instead
Colon No Longer Valid In When Statements
Ruby 1.9
irb(main):001:0> case 'a'; when /\w/: puts 'word'; end
SyntaxError: (irb):1: syntax error, unexpected ':',
expecting keyword_then or ',' or ';' or '\n'
Ruby 1.8.6
irb(main):001:0> case 'a'; when /\w/: puts 'word'; end
word
Action: Use semicolon, then, or newline
Block Variables Now Shadow Local Variables
Ruby 1.9
irb(main):001:0> i=0; [1,2,3].each {|i|}; i
=> 0
irb(main):002:0> i=0; for i in [1,2,3]; end; i
=> 3
Ruby 1.8.6
irb(main):001:0> i=0; [1,2,3].each {|i|}; i
=> 3
Hash.index Deprecated
Ruby 1.9
irb(main):001:0> {1=>2}.index(2)
(irb):18: warning: Hash#index is deprecated; use Hash#key
=> 1
irb(main):002:0> {1=>2}.key(2)
=> 1
Ruby 1.8.6
irb(main):001:0> {1=>2}.index(2)
=> 1
Action: Use Hash.key
Fixnum.to_sym Now Gone
Ruby 1.9
irb(main):001:0> 5.to_sym
NoMethodError: undefined method 'to_sym' for 5:Fixnum
Ruby 1.8.6
irb(main):001:0> 5.to_sym
=> nil
(Cont'd) Ruby 1.9
# Find an argument value by name or index.
def [](index)
lookup(index.to_sym)
end
svn.ruby-lang.org/repos/ruby/trunk/lib/rake.rb
Hash Keys Now Unordered
Ruby 1.9
irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"}
=> {:a=>"a", :c=>"c", :b=>"b"}
Ruby 1.8.6
irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"}
=> {:a=>"a", :b=>"b", :c=>"c"}
Order is insertion order
Stricter Unicode Regular Expressions
Ruby 1.9
irb(main):001:0> /\x80/u
SyntaxError: (irb):2: invalid multibyte escape: /\x80/
Ruby 1.8.6
irb(main):001:0> /\x80/u
=> /\x80/u
tr and Regexp Now Understand Unicode
Ruby 1.9
unicode(string).tr(CP1252_DIFFERENCES, UNICODE_EQUIVALENT).
gsub(INVALID_XML_CHAR, REPLACEMENT_CHAR).
gsub(XML_PREDEFINED) {|c| PREDEFINED[c.ord]}
pack and unpack
Ruby 1.8.6
def xchr(escape=true)
n = XChar::CP1252[self] || self
case n when *XChar::VALID
XChar::PREDEFINED[n] or
(n>128 ? n.chr : (escape ? "&##{n};" : [n].pack('U*')))
else
Builder::XChar::REPLACEMENT_CHAR
end
end
unpack('U*').map {|n| n.xchr(escape)}.join
BasicObject More Brutal Than BlankSlate
Ruby 1.9
irb(main):001:0> class C < BasicObject; def f; Math::PI; end; end; C.new.f
NameError: uninitialized constant C::Math
Ruby 1.8.6
irb(main):001:0> require 'blankslate'
=> true
irb(main):002:0> class C < BlankSlate; def f; Math::PI; end; end; C.new.f
=> 3.14159265358979
Action: Use ::Math::PI
Delegation Changes
Ruby 1.9
irb(main):002:0> class C < SimpleDelegator; end
=> nil
irb(main):003:0> C.new('').class
=> String
Ruby 1.8.6
irb(main):002:0> class C < SimpleDelegator; end
=> nil
irb(main):003:0> C.new('').class
=> C
irb(main):004:0>
Defect 17700
Use of $KCODE Produces Warnings
Ruby 1.9
irb(main):004:1> $KCODE = 'UTF8'
(irb):4: warning: variable $KCODE is no longer effective; ignored
=> "UTF8"
Ruby 1.8.6
irb(main):001:0> $KCODE = 'UTF8'
=> "UTF8"
instance_methods Now an Array of Symbols
Ruby 1.9
irb(main):001:0> {}.methods.sort.last
=> :zip
Ruby 1.8.6
irb(main):001:0> {}.methods.sort.last
=> "zip"
Action: Replace instance_methods.include? with method_defined?
Source File Encoding
Basic
# coding: utf-8
Emacs
# -*- encoding: utf-8 -*-
Shebang
#!/usr/local/rubybook/bin/ruby
# encoding: utf-8
Real Threading
Race Conditions
Implicit Ordering Assumptions
Test Code
What's New?
Alternate Syntax for Symbol as Hash Keys
Ruby 1.9
{a: b}
redirect_to action: show
Ruby 1.8.6
{:a => b}
redirect_to :action => show
Block Local Variables
Ruby 1.9
[1,2].each {|value; t| t=value*value}
Inject Methods
Ruby 1.9
[1,2].inject(:+)
Ruby 1.8.6
[1,2].inject {|a,b| a+b}
to_enum
Ruby 1.9
short_enum = [1, 2, 3].to_enum
long_enum = ('a'..'z').to_enum
loop do
puts "#{short_enum.next} #{long_enum.next}"
end
No block? Enum!
Ruby 1.9
e = [1,2,3].each
Lambda Shorthand
Ruby 1.9
p = -> a,b,c {a+b+c}
puts p.(1,2,3)
puts p[1,2,3]
Ruby 1.8.6
p = lambda {|a,b,c| a+b+c}
puts p.call(1,2,3)
Complex Numbers
Ruby 1.9
Complex(3,4) == 3 + 4.im
Decimal Is Still Not The Default
Ruby 1.9
irb(main):001:0> 1.2-1.1
=> 0.0999999999999999
Regex “Properties”
Ruby 1.9
/\p{Space}/
Ruby 1.8.6
/[:space:]/
Splat in Middle
Ruby 1.9
def foo(first, *middle, last)
(->a, *b, c {p a-c}).(*5.downto(1))
Fibers
Ruby 1.9
f = Fiber.new do
a,b = 0,1
Fiber.yield a
Fiber.yield b
loop do
a,b = b,a+b
Fiber.yield b
end
end
10.times {puts f.resume}
Break Values
Ruby 1.9
match =
while line = gets
next if line =~ /^#/
break line if line.find('ruby')
end
“Nested” Methods
Ruby 1.9
def toggle
def toggle
"subsequent times"
end
"first time"
end
HTH!
One huge difference would be the move from Matz's interpreter to YARV, a bytecode virtual machine that helps significantly with performance.
Many now recommend The Ruby Programming Language over the Pickaxe - more to the point, it has all the details of the 1.8/1.9 differences.
Some more changes:
Returning a splat singleton array:
def function
return *[1]
end
a=function
ruby 1.9 : [1]
ruby 1.8 : 1
array arguments
def function(array)
array.each { |v| p v }
end
function "1"
ruby 1.8: "1"
ruby 1.9: undefined method `each' for "1":String

Resources