Ruby Goldへの道 day2
以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp
2日目 得点 46点/100点中
- クラスインスタンス変数は特異メソッドからアクセスできる
class C @val = 3 # クラスインスタンス変数 attr_accessor :val # 特異クラスのクラスインスタンス変数 class << self @val = 10 end def initialize @val *= 2 if val end end c = C.new c.val += 10 p c.val #=> undefined method `+' for nil:NilClass (NoMethodError)
-tと-fはオプションがない 昨日も同じとこ間違えた〜 forceとtailはないで覚えておこう。
複数回includeされた場合は、後に宣言された方からメソッド探索される
module M1 end module M2 end class C include M1 include M2 end p C.ancestors #=> [C, M2, M1, Object, Kernel, BasicObject]
- クラスCの特異クラスにあるCONSTもコンテキストが異なる
class Object CONST = "100" end class C CONST = "010" class << self CONST = "001" end end p C::CONST #=> "010"
- FixnumとRationalの演算はRationalになる
- 1/2rはRationalのインスタンスが作成される
rが未定義でエラーかと思った。
val = 1 + 1/2r puts val.class #=> Rational
- class << self; endで定義されたメソッドは、特異クラスのインスタンスメソッドになる
module M def method_missing(id, *args) puts "M#method_missing" end end class A include M def method_missing(id, *args) puts "A#method_missing" end end class B < A class << self # 特異クラス def method_missing(id, *args) puts "B.method_missing" end end end B.new.dummy_method #=> A#method_missing
- const_getは、selfに定義された定数を探索する
class Human NAME = "Unknown" def self.name const_get(:NAME) # Fukuzawaクラスのインスタンス end end class Fukuzawa < Human NAME = "Yukichi" end puts Fukuzawa.name #=> Yukichi
- キーワード引数へHashオブジェクトを渡すことができる
def foo(arg1:100, arg2:200) puts arg1 puts arg2 end option = {arg2: 900} foo arg1: 200, **option #=> 200 #=> 900 #foo(arg1: 200, arg2: 900)になる
- キーワード引数は省略できない これも昨日やったような、、、
def foo(arg:) puts arg end foo 100 #=> wrong number of arguments # 下記のように書き換える def foo(arg:) puts arg end foo arg: 100 # <= arg: は省略できない
- Enumerator::Yielderを評価するには、<<を呼び出す
enum_char = Enumerator.new do |yielder| "apple".each_char do |chr| yielder << chr # Enumerator::Yielderの評価 end end array = enum_char.map do |chr| chr.ord end p array #=> [97, 112, 112, 108, 101]
- succ ≒ next selfの次の文字列を返す
class Object CONST = "1" def const_succ CONST.succ! # 1,2,... end end class Child1 const_succ class << self const_succ end end class Child2 const_succ def initialize const_succ end end Child1.new Child2.new p Object::CONST #=> "5"
- Module.nestingはネストの状態を表示する
モジュールがネストされた場合全ての状態を表示する
module SuperMod end module SuperMod::BaseMod p Module.nesting #=> [SuperMod::BaseMod] end
- レキシカルスコープに定数がない場合は、スーパークラスの探索を行う
class Ca CONST = "001" end class Cb CONST = "010" end class Cc CONST = "011" end class Cd CONST = "100" end module M1 class C0 < Ca class C1 < Cc class C2 < Cd p CONST #=> "100" # C2のスーパークラスCdを探索 class C2 < Cb end end end end end
- ブロック変数に*argsを渡すことができる
def hoge(*args, &block) block.call(args) end hoge(1,2,3,4) do |*args| # [[1, 2, 3, 4]]が渡される p args.length < 0 ? "hello" : args #=> [[1, 2, 3, 4]] end
- sort!は破壊的メソッド
大きい順に並び替える
class Company attr_reader :id attr_accessor :name def initialize id, name @id = id @name = name end def to_s "#{id}:#{name}" end def <=> other other.id <=> self.id end end companies = [] companies << Company.new(2, 'Liberyfish') companies << Company.new(3, 'Freefish') companies << Company.new(1, 'Freedomfish') companies.sort! # 大きい順に並び替える companies.each do |e| puts e end # 3:Freefish # 2:Liberyfish # 1:Freedomfish
- freezeはオブジェクトの破壊的な変更を禁止する
array = ["a", "b", "c"].freeze array = array.map!{|content| content.succ} p array #=> can't modify frozen Array: ["a", "b", "c"] (FrozenError)
- method_missingは、継承チェーンを辿った末にメソッドが見つからなかった場合に呼び出される
class Class def method_missing(id, *args) puts "Class#method_missing" end end class A def method_missing(id, *args) puts "A#method_missing" end end class B < A def method_missing(id, *args) puts "B#method_missing" end end p B.class # Class ??? B.dummy_method #=> Class#method_missing # Classクラスのインスタンスメソッドが呼ばれる
- raiseの例外クラスを省略した場合は、RuntimeErrorを発生させる
RuntimeErrorはstanderdErrorのサブクラス
begin raise "Err!" rescue => e puts e.class #=> RuntimeError end
- ブロックにあるローカル変数valはトップレベルにあるものと同じ
val = 100 def method(val) yield(15 + val) end _proc = Proc.new{|arg| val + arg } p method(val, &_proc) #=> 215
- const_defined? 指定された名前の定数が定義されていたら真を返す
mod = Module.new mod.module_eval do EVAL_CONST = 100 end puts "EVAL_CONST is defined? #{mod.const_defined?(:EVAL_CONST, false)}" #=> EVAL_CONST is defined? false puts "EVAL_CONST is defined? #{Object.const_defined?(:EVAL_CONST, false)}" #=> EVAL_CONST is defined? true
- Fiberは軽量スレッドを提供する
f = Fiber.new do Fiber.yield 15 5 end f.resume f.resume # f.resume 三回以上呼び出すとエラーになる
- requireはライブラリのロード、loadは設定ファイルの読み込みに用いる。
# lib.rb module Lib $num += 1 end ## # 実行ファイル $num = 0 1..10.times do |n| require './lib.rb' end puts $num #=> 1
require 'json' json = <<JSON { "price":100, "order_code":200, "order_date":"2018/09/20", "tax":0.8 } JSON using_parse = JSON.parse json p using_parse #=> {"price"=>100, "order_code"=>200, "order_date"=>"2018/09/20", "tax"=>0.8} using_load = JSON.load json p using_parse #=> {"price"=>100, "order_code"=>200, "order_date"=>"2018/09/20", "tax"=>0.8}
- 破壊的な変更できない また出た
CONST_LIST_A = ['001', '002', '003'] begin CONST_LIST_A.map{|id| id << 'hoge'} # 値変更する rescue end CONST_LIST_B = ['001', '002', '003'].freeze begin CONST_LIST_B.map{|id| id << 'hoge'} # 値変更する rescue end CONST_LIST_C = ['001', '002', '003'].freeze begin CONST_LIST_C.map!{|id| id << 'hoge'} # 値変更しない(破壊的メソッド) rescue end CONST_LIST_D = ['001', '002', '003'].freeze begin CONST_LIST_D.push('add') # 値変更しない rescue end p CONST_LIST_A #=> ["001hoge", "002hoge", "003hoge"] p CONST_LIST_B #=> ["001hoge", "002hoge", "003hoge"] p CONST_LIST_C #=> ["001", "002", "003"] p CONST_LIST_D #=> ["001", "002", "003"]