Is the &method(:method_name) idiom bad for performance in Ruby?
Yes, it appears to be bad for performance.
def time
start = Time.now
yield
"%.6f" % (Time.now - start)
end
def do_nothing(arg)
end
RUBY_VERSION # => "1.9.2"
# small
ary = *1..10
time { ary.each(&method(:do_nothing)) } # => "0.000019"
time { ary.each { |arg| do_nothing arg } } # => "0.000003"
# large
ary = *1..10_000
time { ary.each(&method(:do_nothing)) } # => "0.002787"
time { ary.each { |arg| do_nothing arg } } # => "0.001810"
# huge
ary = *1..10_000_000
time { ary.each(&method(:do_nothing)) } # => "37.901283"
time { ary.each { |arg| do_nothing arg } } # => "1.754063"
It looks like this is addressed in JRuby:
$ rvm use jruby
Using /Users/joshuajcheek/.rvm/gems/jruby-1.6.3
$ xmpfilter f.rb
def time
start = Time.now
yield
"%.6f" % (Time.now - start)
end
def do_nothing(arg)
end
RUBY_VERSION # => "1.8.7"
# small
ary = *1..10
time { ary.each(&method(:do_nothing)) } # => "0.009000"
time { ary.each { |arg| do_nothing arg } } # => "0.001000"
# large
ary = *1..10_000
time { ary.each(&method(:do_nothing)) } # => "0.043000"
time { ary.each { |arg| do_nothing arg } } # => "0.055000"
# huge
ary = *1..10_000_000
time { ary.each(&method(:do_nothing)) } # => "0.427000"
time { ary.each { |arg| do_nothing arg } } # => "0.634000"
Is there a more concise way to call an outside method on a map in Ruby?
Yes, possible this way, but not good for performance (see post: Is the &method(:method_name) idiom bad for perfomance in Ruby?):
targets = ['./foo', './bar', './free']
targets.map(&Dir.method(:exists?))
# => [false, false, false] #all are false,as I don't have such directories.
Dynamic method calling in Ruby
is there any reason to ever use
send
?
call
needs a method object, send
doesn't:
class Foo
def method_missing(name)
"#{name} called"
end
end
Foo.new.send(:bar) #=> "bar called"
Foo.new.method(:bar).call #=> undefined method `bar' for class `Foo' (NameError)
is there any reason to ever use
eval
?
eval
evaluates arbitrary expressions, it's not just for calling a method.
Regarding benchmarks, send
seems to be faster than method
+ call
:
require 'benchmark'
class Foo
def bar; end
end
Benchmark.bm(4) do |b|
b.report("send") { 1_000_000.times { Foo.new.send(:bar) } }
b.report("call") { 1_000_000.times { Foo.new.method(:bar).call } }
end
Result:
user system total real
send 0.210000 0.000000 0.210000 ( 0.215181)
call 0.740000 0.000000 0.740000 ( 0.739262)
Shorter way to pass every element of an array to a function
You can do this
@files.map(&method(:read))
But be aware though about performance.
Is there a ruby idiom for returning the first array element, if only one exists?
You seem to want to handle the case of val array being undefined so...
val.size > 1 ? val : val[0] if defined?(val)
But as has been pointed out it would be better to deliver a consistent argument (always arrays) so the following will deliver the val array or an empty array if undefined
defined?(val) ? val : []
Which gives me better performance Activerecord find_by or where?
where
gives you marginally better performance. find_by
is implemented through method_missing
magic; method_missing
requires a call to the object's method table to see if there's an existing method first, and if not then a call to method_missing
, whereas where
just finds the method correctly.
To see actual benchmarks of this, check out this post.
does ruby have an elegant way to say array2 = some_lookup_method(array1)
You can use the map command, which will return a new array with the results of your code block:
long_code = short_code.map{ |code| my_lookup_long_code(code) }
How do I pass an argument to array.map short cut?
You can't do it like this. The &
operator is for turning symbols into procs.
a = [1, 2, 3, 4, 5]
puts a.map(&:to_s) # prints array of strings
puts a.map(&:to_s2) # error, no such method `to_s2`.
&
is a shorthand for to_proc
:
def to_proc
proc { |obj, *args| obj.send(self, *args) }
end
It creates and returns new proc. As you see, you can't pass any parameters to this method. You can only call the generated proc.
Related Topics
What's the Precedence of Ruby'S Method Call
Convert Unicode Codepoint to String Character in Ruby
Rails 3.1 Limit User Created Objects
Ruby Local Variable Is Undefined
Why Do Two Strings Separated by Space Concatenate in Ruby
Ruby Gem For Finding Timezone of Location
How to Define Action With Simple Form For
Rake "Already Initialized Constant Wfkv_" Warning
Get Index of Array Element Faster Than O(N)
Get Current Stack Trace in Ruby Without Raising an Exception