Ruby 2.0.0-rc1 is out, and the big stuff has already been pretty well-covered – lazy enumerators, keyword arguments, Module#prepend (although I hope to cover that a little later, to show an example of why I’m so excited about it). Refinements are in there but experimental, and I wouldn’t bet on them staying for too long.
There’s more fun stuff in the NEWS file, though.
Kernel#caller_locations. This isn’t very well-documented (something in Ruby poorly documented? no way!) It’s a close parallel to Kernel#caller, which you may have used before:
>> pp caller ["/home/mboeh/.rvm/rubies/ruby-2.0.0-rc1/lib/ruby/2.0.0/irb/workspace.rb:86:in `eval'", "/home/mboeh/.rvm/rubies/ruby-2.0.0-rc1/lib/ruby/2.0.0/irb/workspace.rb:86:in `evaluate'", "/home/mboeh/.rvm/rubies/ruby-2.0.0-rc1/lib/ruby/2.0.0/irb/context.rb:366:in `evaluate'", ...]
On first blush, caller_locations seems to do the same thing:
>> pp caller_locations ["/home/mboeh/.rvm/rubies/ruby-2.0.0-rc1/lib/ruby/2.0.0/irb/workspace.rb:86:in `eval'", "/home/mboeh/.rvm/rubies/ruby-2.0.0-rc1/lib/ruby/2.0.0/irb/workspace.rb:86:in `evaluate'", "/home/mboeh/.rvm/rubies/ruby-2.0.0-rc1/lib/ruby/2.0.0/irb/context.rb:366:in `evaluate'", ...]
But in the second example, those aren’t actually Strings!
>> caller.first.class => String >> caller_locations.first.class => Thread::Backtrace::Location
Thread::Backtrace::Location is also minimally documented, but it essentially provides structured access to the data that makes up each line of the backtrace.
>> caller_locations.first.absolute_path => "/home/mboeh/.rvm/rubies/ruby-2.0.0-rc1/lib/ruby/2.0.0/irb/workspace.rb" >> caller_locations.first.label => "eval" >> caller_locations.first.lineno => 86
This should make any code that has to print, rewrite, or otherwise reflect on and manipulate the backtrace cleaner and more obvious. Thread#backtrace_locations provides the same functionality versus Thread#backtrace.
Thread-local variables. In Ruby 1.9, thread-local variables (as accessed with Thread# and friends) are actually Fiber-local variables. Ruby 2.0 keeps this behavior but also includes Thread#thread_variable_get and Thread#thread_variable_set, which appear to be scoped to the current Thread. The Fiber-local behavior had been causing problems with concurrency libraries like Celluloid (which uses Fibers heavily) and ActiveRecord, which used thread-local variables to store a checked-out connection from the connection pool. Fiber-heavy code ended up checking out many more connections than was warranted.
Module#const_get. Have you ever found yourself writing non-Rails code and really wanting String#constantize? I’ve copied around a minimal implementation of that method more often than I’d care to say. Well, now const_get does it for you.
>> Kernel.const_get "Thread::Backtrace::Location" => Thread::Backtrace::Location
Lots more in there, too.