Just curious about it.
If you open the IRB and type _, you'll get nil as response:
irb(main):001:0> _
=> nil
And you can modify its value:
irb(main):002:0> _ = 'some value'
irb(main):003:0> _
=> "some value"
But if you create a new variable with _, its value is modified:
irb(main):004:0> foo_bar = 'other value'
irb(main):005:0> _
=> "other value"
Why? Is this a design decision?
irb uses _ to refer to the value of last calculated expression. So you will see _ changed even if you don't use it in the previous line :)
Within irb, _ returns the result of the previous operation. So on opening a new irb session _ will equal nil as there was no previous operation
2.0.0p353 :001 > 4
=> 4
2.0.0p353 :002 > 3 + _
=> 7
Related
Could someone please explain the difference between:
&.[](:key)
.try(:[],:key)
.try(:key)
Specially what the "[]" represents in the first and second?
.[] is a method on the Hash object.
x.[](:key) calls the [] method with the :key argument and is equivalent to x[:key]
& is the safe navigation operator. x&.[](:key) would return nil if x is nil while x.[](:key) would cause an error.
x = {key: 123}
x[:key]
# => 123
x.[](:key)
# => 123
x = nil
x.[](:key)
# NoMethodError: undefined method `[]' for nil:NilClass
x&.[](:key)
# => nil
As far as the differences go, I don't believe there are any between the first and second, however x.try(:key) would try to call a key method on x and that would error out because it doesn't exist.
x.try(:[], :key) calls the .[] method with :key as an argument and is equivalent to what we saw above. As with the safe navigation operator, try returns nil if x is nil.
For better understanding, [] is a special method similar to fetch on Hash:
hash = {a: 1}
hash.[](:a) # => 1
hash.fetch(:a) # => 1
try is from Rails, could be used with syntax Hash#try(:method, argument):
hash.try(:[], :a) # => 1
hash.try(:fetch, :a) # => 1
I am confused with how puts _|_ works in Ruby. If you type in a variable and then call that statement
3
puts _|_
you get the name of the variable followed by nil
3
=> nil
However, if you type it again, you get false
puts _|_
=> false
It doesn't seem like one of those Perl-like variables that begin with a dollar sign.
What in the world does this weird symbol mean and how does it work?
The underscore in a console (IRB or pry) stands for the result of the previous command. So
3
=> 3
puts _|_
3
=> nil
Here the above puts statement becomes equivalent to
puts 3 <bit-wise or> 3
which puts 3|3 equals puts 3.
Since puts returns nil, when you repeat the puts _|_ it becomes
puts nil|nil
... which is puts false.
In ruby _ is a valid identifier.
In IRB _ contains the value of the last expression.
2.1.5 :001 > 100
=> 100
2.1.5 :002 > _
=> 100
_ is a ruby special variable, it is used to get the result of the previous expression.
irb(main):030:0> 3
=> 3
irb(main):031:0> _
=> 3
irb(main):032:0> _.to_s
=> "3"
irb(main):033:0> _
=> "3"
A ruby variable whose name begins with a lowercase letter (a-z) or underscore (_) is a local variable or method invocation. Uninitialized instance variables have a value of nil.
irb(main):001:0> _
=> nil
irb(main):002:0> _ | _
=> false
irb(main):003:0> nil | nil
=> false
_ is a ruby special variable, this variable stores out put of the previous expression/command, so when you do:
1.9.3-p0 :043 > 3
=> 3
'_' contains the value 3, because return value of previous expression is 3. When you use puts as below:
1.9.3-p0 :045 > puts _|_
3
=> nil
its return value is nil.Next time when you execute the | as below:
1.9.3-p0 :049 > _|_
=> false
it returns false because it is same as below expression:
1.9.3-p0 :050 > nil|nil
=> false
that is why puts | returns false.
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"
I want to be able to check if a word is already all uppercase. And it might also include numbers.
Example:
GO234 => yes
Go234 => no
You can compare the string with the same string but in uppercase:
'go234' == 'go234'.upcase #=> false
'GO234' == 'GO234'.upcase #=> true
a = "Go234"
a.match(/\p{Lower}/) # => #<MatchData "o">
b = "GO234"
b.match(/\p{Lower}/) # => nil
c = "123"
c.match(/\p{Lower}/) # => nil
d = "µ"
d.match(/\p{Lower}/) # => #<MatchData "µ">
So when the match result is nil, it is in uppercase already, else something is in lowercase.
Thank you #mu is too short mentioned that we should use /\p{Lower}/ instead to match non-English lower case letters.
I am using the solution by #PeterWong and it works great as long as the string you're checking against doesn't contain any special characters (as pointed out in the comments).
However if you want to use it for strings like "Überall", just add this slight modification:
utf_pattern = Regexp.new("\\p{Lower}".force_encoding("UTF-8"))
a = "Go234"
a.match(utf_pattern) # => #<MatchData "o">
b = "GO234"
b.match(utf_pattern) # => nil
b = "ÜÖ234"
b.match(utf_pattern) # => nil
b = "Über234"
b.match(utf_pattern) # => #<MatchData "b">
Have fun!
You could either compare the string and string.upcase for equality (as shown by JCorc..)
irb(main):007:0> str = "Go234"
=> "Go234"
irb(main):008:0> str == str.upcase
=> false
OR
you could call arg.upcase! and check for nil. (But this will modify the original argument, so you may have to create a copy)
irb(main):001:0> "GO234".upcase!
=> nil
irb(main):002:0> "Go234".upcase!
=> "GO234"
Update: If you want this to work for unicode.. (multi-byte), then string#upcase won't work, you'd need the unicode-util gem mentioned in this SO question
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.