Created
November 2, 2012 14:13
-
-
Save matsadler/4001581 to your computer and use it in GitHub Desktop.
A few examples of the ruby 2.0.0 preview 1 highlights given in http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/46348
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Ruby 2.0.0 preview 1 highlights | |
# A few examples of the highlights given in | |
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/46348 | |
# Refinements | |
# =========== | |
# create a namespaced refinement | |
module NumberQuery | |
refine String do | |
def number? | |
match(/^[1-9][0-9]+$/) ? true : false | |
end | |
end | |
end | |
# it's not available outside that namespace | |
begin | |
"123".number? | |
rescue => e | |
p e #=> #<NoMethodError: undefined method `number?' for "123":String> | |
end | |
# it is inside! | |
module NumberQuery | |
p "123".number? #=> true | |
end | |
# or you can add it to another namespace like so | |
module MyApp | |
using NumberQuery | |
p "123".number? #=> true | |
p "foo".number? #=> false | |
end | |
# Keyword arguments | |
# ================= | |
def wrap(string, before: "<", after: ">") | |
"#{before}#{string}#{after}" # no need to retrieve options from a hash | |
end | |
# optional | |
p wrap("foo") #=> "<foo>" | |
# one or the other | |
p wrap("foo", before: "#<") #=> "#<foo>" | |
p wrap("foo", after: "]") #=> "<foo]" | |
# order not important | |
p wrap("foo", after: "]", before: "[") #=> "[foo]" | |
# double splat to capture all keyword arguments, or use as hash as keyword | |
# arguments | |
def capture(**opts) | |
opts | |
end | |
p capture(foo: "bar") #=> {:foo=>"bar"} | |
# keys must be symbols | |
opts = {:before => "(", :after => ")"} | |
p wrap("foo", **opts) #=> "(foo)" | |
# the old hash style syntax is still accepted for keyword arguments | |
p wrap("foo", :before => "{", :after => "}") #=> "{foo}" | |
# Enumerator#lazy | |
# =============== | |
# making an enumerable lazy makes it possible to enumerate infinite collections | |
require "timeout" | |
begin | |
timeout(1) {[1,2,3].cycle.map {|x| x * 10}} | |
rescue => e | |
p e #=> #<Timeout::Error: execution expired> | |
end | |
p [1,2,3].lazy.cycle.map {|x| x * 10}.take(5).to_a #=> [10, 20, 30, 10, 20] | |
# a lazy enumerable will evaluate the entire chain for each element at a time, | |
# rather than all elements at each stage of the chain, so the following will | |
# output at 1 second intervals. Without #lazy all output would come after 3 | |
# seconds | |
class Foo | |
include Enumerable | |
def each | |
sleep 1 | |
yield 1 | |
sleep 1 | |
yield 2 | |
sleep 1 | |
yield 3 | |
end | |
end | |
Foo.new.lazy.map {|x| x * 10}.each {|x| p x} | |
# you would think that as the collection is only iterated once #lazy might | |
# speed things up, unfortunately this generally isn't the case | |
# Module#prepend | |
# ============== | |
module A | |
def foo | |
"A" | |
end | |
end | |
# regular module include, the method in the class overrides the module | |
# (module method is available as `super`) | |
class B | |
include A | |
def foo | |
"B" | |
end | |
end | |
p B.new.foo #=> "B" | |
# with prepend the module method overides that in the class | |
# (in the case the method in the class is available as super) | |
class C | |
prepend A | |
def foo | |
"B" | |
end | |
end | |
p C.new.foo #=> "A" | |
# Converting convention to Hash: #to_h | |
# ==================================== | |
p({:foo => 1}.to_h) #=> {:foo=>1} | |
Baz = Struct.new(:foo) | |
baz = Baz.new(1) | |
p baz.to_h #=> {:foo=>1} | |
# so instead of writing something overly strict like: | |
def foo(opts) | |
raise ArgumentError, "opts must be a Hash" unless opts.is_a?(Hash) | |
# do stuff with opts | |
end | |
# we can go with the more versatile: | |
def foo(options) | |
if options.respond_to?(:to_h) | |
opts = options.to_h | |
else | |
raise TypeError, "can't convert #{options.inspect} into Hash" | |
end | |
# do stuff with opts | |
end | |
# %i: a literal for symbol array | |
# ============================== | |
p %i{hurray huzzah whoop} #=> [:hurray, :huzzah, :whoop] | |
# regexp engine is changed to Onigmo | |
# ================================== | |
# The is a fork of the Oniguruma regexp engine used by 1.9, with a few more | |
# features. More details at https://github.com/k-takata/Onigmo | |
# The new features seem Perl-inspired, this seems to be a good refrence: | |
# http://perldoc.perl.org/perlre.html | |
# (?(cond)yes|no) | |
# if cond is matched, then match against yes, if cond is false match against no | |
# cond refrences a match either by group number or name, or is a | |
# look-ahead/behind | |
# example only matches a trailing cap if there is a leading cap | |
regexp = /^([A-Z])?[a-z]+(?(1)[A-Z]|[a-z])$/ | |
regexp =~ "foo" #=> 0 | |
regexp =~ "foO" #=> nil | |
regexp =~ "FoO" #=> 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment