gem 'rubocop-performance', require: false
или
gem 'rubocop'
Автоматом выполнить правки в файле
rubocop --require rubocop-performance benchmark2.rb -A
или
rubocop benchmark2.rb -A
Ставим: gem install fasterer, запускаем fasterer, можно передать в параметром адрес файла.
выдал Array#select.first is slower than Array#detect. проводим эксперимент:
require 'benchmark/ips'
data = [*0..100_000_000]
pp data.detect { | doc | doc > 1000 }
pp data.select { | doc | doc > 1000 }.first
Benchmark.ips do |x|
x.report('detect') {
data.detect { | doc | doc > 1000 }
}
x.report('select#select') {
data.select { | doc | doc > 1000 }.select
}
x.compare!
end
detect: 19387.9 i/s
select#select: 0.2 i/s - 87530.48x slower В рот мне ноги одним словом
gem 'benchmark-ips' для бренчмарка.
Всегда интересовало оператор безопасной навигации или пресловутый амперсанд перед вызовом метода на объекте сильно тормозит работу? оказываеться нет, вообще не тормозит, пихаем его везде:)
require "benchmark/ips"
HASH =Hash[*("a".."zzz").to_a.shuffle]
KEY = "zz"
def key_fast
HASH.keys.first.to_s
end
def key_slow
HASH&.keys&.first&.to_s
end
Benchmark.ips do |x|
x.report("Hash#&?") { key_slow }
x.report("Hash#_?") { key_fast }
x.compare!
end
bsearch вообще никогда не использовал, а оказалось он мега быстрый
require 'benchmark/ips'
data = [*0..100_000_000]
Benchmark.ips do |x|
x.report('find') { data.find { |number| number > 77_777_777 } }
x.report('bsearch') { data.bsearch { |number| number > 77_777_777 } }
x.compare!
end
про блок, yield
require_relative 'MyTest'
require_relative 'config'
p MyTest.extension
MyTest.rb
module MyTest
class << self
attr_accessor :extension
def config
yield self
endmy_proc= Proc.new {|msg| puts msg }
my_proc2= proc {|msg| puts msg }
my_lambda = lambda {|msg| puts msg }
my_lambda2 = ->(msg) {puts msg }
my_proc.call("hello")
my_proc2.call("hello mir")
my_lambda.call("hello cat")
my_lambda.call("hello dog")
end
end
config.rb
MyTest.config do |config|
config.extension = '.txt'
end
так как нам не нужно создавать экземпляр модуля, такое прокатывает. мы создаем синглтон класс для модуля, обращаемся к нему и передаем блок "config.extension = '.txt'" yield self - мы передаем выполняемый блок селф. то есть имя модуля MyTest.
способы вызова лямбы и прок
my_proc= Proc.new {|msg| puts msg }
my_proc2= proc {|msg| puts msg }
my_lambda = lambda {|msg| puts msg }
my_lambda2 = ->(msg) {puts msg }
my_proc.call("hello")
my_proc2.call("hello mir")
my_lambda.call("hello cat")
my_lambda.call("hello dog")
отличие прок и лямбды, число аргументов, rerurn
def testmethod(callable)
result = callable.call("hello")
puts "result = #{result}"
puts "inspect = #{callable.inspect}"
end
my_lambda = proc do |x| //для тестирования замени на lambda
puts x
return x
end
testmethod(my_lambda)
в lambda дополнительно выполняться puts "result = #{result}" puts "inspect = #{callable.inspect}"
прок не будет ругаться на лишние аргументы, лямбда будет ругаться на не верное количество переданных аргументов.
блок можно передавать 1, проков и лямбд хоть сколько, а дальше
# вариант 1, передаем в метод блок
def bloc_method
yield "hello test"
end
bloc_method do |msg|
puts msg
end
# вариант 1
# вариант 2 передаем в метод блок
def bloc_method2(&myblock)
myblock.call("hello wold")
end
bloc_method2 do |msg|
puts msg
end
# вариант 2
# вариант 3 передаем в метод лямбду преобразованную в блок
def bloc_method3
yield "test hello"
end
l = -> (msg) {puts msg}
bloc_method3 &l
# вариант 3
# вариант 4 передаем в метод блок, лямбду и процедуру
def bloc_method(my_proc3,my_lambda3)
yield "hello test"
my_proc3.call("hello cat")
my_lambda3.call("hello dog")
end
my_proc3= proc {|msg| puts msg }
my_lambda3 = lambda {|msg| puts msg }
bloc_method(my_proc3,my_lambda3) do |msg|
puts msg
end
Когда нужно бегать между ветками а коммитить мелочь мы не хотим пользуемся такой замечательной штукой как git stash
Спрятать все : git stash
Достать последнее : git stash apply
class B
class << self # внутри этого блока можно вставить много синглтон методов для класса
def single
puts "single method"
end
end
# тоже самое
def self.single1
puts "single method"
end
# тоже самое
def B.single2
puts "single method"
end
end
А посмотреть синглтон классы можем вот так
puts B.singleton_class.instance_methods.grep /single/
и вот тут я до сих пор не понял, почему B.singleton_class.methods отрабатывает по другому
instance_methods выводит методы экземпляра класса
methods выводит методы для объекта для которого его вызываем.
ну а методы класса можно получить так puts (B.methods - B.instance_methods)
Еще можно было назвать эффект бабочки, короче все классы наследуют object, а objectвключает в себя модуль Kernel, так что можно в него что то добавить и то что добавили как правило будет во всех наших классах, но это не точно
module Kernel
def my_method
puts "привет из ядра"
end
end
И еще полезной информации от модуля нельзя наследоваться и от модуля нельзя создать новый объект а так модули и классы в руби посути одно и тоже
respond_to method_missing define_method remove_method undef_method instance_eval 6 непонятных фраз на англицком языке, жеваный крот !
respond_to
[1,2,3].respond_to?(:count)
method_missing переопределяя этот метод, он будет вызван в тех случаях когда метода нет
def method_missing(method, *args)
method # имя метода которого нет
args[0] # аргументы переданные в метод
end
define_method() уменьшает объем кода когда нужно создать много методов с однотипным кодом внутри.
@data={
:user="123456",
:tmail="tmail.ru",
:food="free"
}
# Используя метод define_method:
%w(user email food).each do |meth|
define_method(meth) { @data[meth.to_sym] }
end
p user
p tmail
p food
remove_method удаление методов в классе, но не трогаем наследование
class A
def x
puts "x from A class"
end
end
class B < A
def x
puts "x from B Class"
end
remove_method :x
end
obj = B.new
obj.x
undef_method удаление методов то же самое но удаляем и то что наследовали
instance_eval динамически определит метод в экземпляре класса
class A
def x
puts "x from A class"
end
end
class B < A
def x
puts "x from B Class"
end
undef_method :x
end
obj = B.new
obj.instance_eval do
def color
"green"
end
end
p obj.color
require добавляете методы модуля как методы класса
include как методы экземпляра класса
require_relative относительно файла в котором ее вызываем, так же как и в require .rb можно не писать
module A
def say
puts "this is module A"
end
end
class B
include A
end
class C
def saymethods
end
extend A
end
class E
def say
puts "this is module E"
end
end
p B.methods.grep /say/
B.new.say
p C.say
p C.new.methods.grep /sa/
p E.new.say
К сахару данный пост имеет мало отношения, просто запомнил что опускание скобочек при передачи аргументов в методы руби так называется.
а из интересного посмотрим методы и отфильтруем те что содержат квадратную скобку
args=["Ivanov","Ivan"]
p args.methods.grep /\[/
а вот и сахар
args=["Ivanov","Ivan"]
p args.[](1)
args.[]=(1,1)
p args[1]
то есть когда мы используем массив и в квадратных скобках индекс мы по сути вызываем метод который называеться [] и передаем ему индекс в качестве аргумента
Скрытый nil, просто красивый код когда нужно вернуть nil
require 'digest'
def hash(*args)
return unless args.any?
Digest::MD5.hexdigest args.join(' ')
end
args=["Ivanov","Ivan"]
p hash(args)
p hash()
если мы не передали аргументов то по сути у нас пустой массив
args=[]
p args.any?
any? от пустого массива false,
unless false сработает и return вернет то что указано до unless, то есть ничего