ruby学習しての感想 ~2024/08/17

.included_modulesメソッド便利。
継承しているモジュールが分かる。
[5] pry(main)> Array.included_modules
=> [ActiveSupport::ToJsonWithActiveSupportEncoder,
JSON::Ext::Generator::GeneratorMethods::Array,
MessagePack::CoreExt,
Enumerable,
ActiveSupport::Dependencies::ZeitwerkIntegration::RequireDependency,
ActiveSupport::ToJsonWithActiveSupportEncoder,
PP::ObjectMixin,
ActiveSupport::Tryable,
ActiveSupport::Dependencies::Loadable,
JSON::Ext::Generator::GeneratorMethods::Object,
Kernel]

rubyではオブジェクト自身が使えるインスタンスメソッドや、クラスが使えるインスタンスメソッドや、継承しているモジュールを調べることができる

pやputsメソッドはKernelモジュールの特異メソッドとして定義されている。
なので、Kernelというレシーバーを指定しても実行できるし、Kernelモジュールは他のクラスにもincludeされているので、インスタンスメソッドとしても使える
[12] pry(main)> Kernel.p 12
12
=> 12
[13] pry(main)> Kernel.puts 12
12
=> nil

クラスが継承している親クラスをその親のクラス + ミックスインしている全てのモジュールはancestorsメソッドで調べることができる
[15] pry(main)> String.ancestors
=> [ActiveSupport::ToJsonWithActiveSupportEncoder,
String,
JSON::Ext::Generator::GeneratorMethods::String,
MessagePack::CoreExt,
Comparable,
ActiveSupport::Dependencies::ZeitwerkIntegration::RequireDependency,
ActiveSupport::ToJsonWithActiveSupportEncoder,
Object,
PP::ObjectMixin,
ActiveSupport::Tryable,
ActiveSupport::Dependencies::Loadable,
JSON::Ext::Generator::GeneratorMethods::Object,
Kernel,
BasicObject]

rubyのprocは関数の中で保有している値を元に何かをして欲しい時に使えそう。
rails的なscopeだとただのjs的なアロー関数使ってます感だけど、
メソッドの中で特定のメソッド呼んで処理させる的なコールバック的な事をやりたい際に向いてそう

rubyで意識することは全てのオブジェクトが何かしらのクラスのオブジェクトを理解することか。
クラスによって使えるメソッドは決まってるから、もしできない事があるならオブジェクトを型変換したり、includeとかして足す感じなのかな

出来上がったオブジェクトに対してto_hする方が、
mapの中でfindで探すとかよりも早い気がする

こうらしい。
配列の方が単純なイメージしたけど、

3万件の2つの要素がある多重配列を作るのと、
それをハッシュ構造で作るのだと、どっちが早い?
rubyだと高速にハッシュを作成できるらしい。
しかし配列の方が早いと予測してきた。
require 'benchmark'
# データの準備
data = (1..30000).map { |i| [i, "value#{i}"] }
# 配列の作成
array_time = Benchmark.realtime do
array = data.map { |k, v| [k, v] }
end
# ハッシュの作成
hash_time = Benchmark.realtime do
hash = data.to_h
end
puts "Array creation time: #{array_time} seconds"
puts "Hash creation time: #{hash_time} seconds"

こんな感じのコードで試したんだけど、そこまで遅くなかった。
SQLでorder指定の方が遅い気がする
require 'benchmark'
# データの準備
data = (1..30000).map { |i| [i, "value#{i}"] }
hash = {}
# ハッシュの作成
hash_time = Benchmark.realtime do
hash = data.to_h
end
puts "Hash creation time: #{hash_time} seconds"
p hash

そんなに遅いようには思えない。
配列にpushして行ってもそこまで遅くない。
SQLよりかはマシ
benchmarkライブラリ便利だなー
require 'benchmark'
# データの準備
data = (1..30000).map { |i| [i, "value#{i}"] }
array = []
hash = {}
# 配列の作成
array_time = Benchmark.realtime do
array << data.map { |k, v| [k, v] }
end
# ハッシュの作成
hash_time = Benchmark.realtime do
hash = data.to_h
end
puts "Array creation time: #{array_time} seconds"
puts "Hash creation time: #{hash_time} seconds"

ここにもあったけど便利で簡単だなー
module Benchmark (Ruby 3.3 リファレンスマニュアル)
ガンガン測定して行こー
require 'benchmark'
n = 50000
Benchmark.bm do |x|
x.report { for i in 1..n; a = "1"; end }
x.report { n.times do ; a = "1"; end }
x.report { 1.upto(n) do ; a = "1"; end }
end
#=>
#
# user system total real
# 1.033333 0.016667 1.016667 ( 0.492106)
# 1.483333 0.000000 1.483333 ( 0.694605)
# 1.516667 0.000000 1.516667 ( 0.711077)