2020-01-14
ツクールに搭載されている Ruby のバージョンは Ace が 1.9.2 で XP と VX が 1.8.1 で、ちょっと古いです。
そこで、便利機能をちょこっと移植したいと思います。
元となる機能とは動作が異なる場合がございます。ご注意ください。

1.ネストされたオブジェクトを再帰的に参照

ネストされた配列などを参照するとき、途中に参照先がなかったりするとエラーになってしまいます。
ary = {
:ichigo => [[111, 112, 113], [121, 122, 123], [131, 132, 133]],
:ringo => [[211, 212, 213], [221, 222, 223], [231, 232, 233]],
:meron => [[311, 312, 313], [321, 322, 323], [331, 332, 333]],
}
ary[:ringo][0][2] #=> 113
ary[:suika][2][1] #=> ERROR
そこで dig メソッドです。参照先がない場合はエラーではなく nil を返してくれます。

Array#dig, Hash#dig
module Digable
def dig(*keys)
obj = self
keys.each_with_index do |k,i|
if obj.respond_to?('dig')
obj = obj[k]
else
n = caller.find_index {|c| c.include?("`#{__callee__}'") } || 2
msg = "#{obj.class} does not have #dig method : index #{i} key #{k}"
raise TypeError, msg, caller[n+1]
end
end
return obj
end
end
class Array
include Digable
end
class Hash
include Digable
end
オブジェクトに dig が定義されていれば、ネストを掘り進めます。
ary.dig(:ringo, 0, 2) #=> 113
ary.dig(:suika, 2, 1) #=> nil


2.ぼっち演算子

Ruby 2.3 より、レシーバが nil だった時にはメソッドを実行しない "ぼっち演算子" という機能が追加されています。
variable && variable.to_i を variable&.to_i とすることができます。
演算子は追加できないので、メソッドで実装します。

Object#try
class Object
def try(method_name)
self && self.__send__(method_name)
rescue NoMethodError => e
e.set_backtrace(caller(2))
raise e
end
end
これは割とよく使う機能ですね。
nil.try(:to_i) #=> nil


3.自分自身を返す

ただただ自分自身を返すメソッドです。
それ以上でもそれ以下でもありません。

Object#itself
class Object
def itself
self
end
end
たまに良く使うかな?そうでもないか?
123.itself #=> 123


4.数値を桁毎の配列にする

Integer#digits
class Integer
def digits
self.to_s.chars.reverse!.map!(&:to_i)
end
end
1桁目の添え字は 0 です。
123.digits #=> [3, 2, 1]


5.ハッシュの値を置き換える

hash.each {|k,v| hash[k] = v.to_s } こういうやつ

Hash#transform_values
class Hash
def transform_values
self.each_with_object({}) {|(k,v),r| r[k] = yield v }
end
def transform_values!
self.each {|k,v| self[k] = yield v }
end
end
!付きの方が破壊的なメソッドです。

では、ある数に使われている数字の種類を数える処理を3~5を使って書いてみるよ。
num = 314159265359
# 使わない場合
p num.to_s.chars.map(&:to_i).sort.each_with_object({}) {|n,h| h[n] = (h[n]||0)+1 }
# 使う場合
p num.digits.sort.group_by(&:itself).transform_values(&:size)
思ったより短く書けた。。。
場合によっては、aaa {|a| a.aa }.bbb {|b| b.bb }.ccc みたいになって読みにくくなるから
aaa(&:aa).bbb(&:bb).ccc って書けて良いよねってことが言いたかった。


6.配列をハッシュに変換

これが無いなんてやってらんない。

Array#to_h
class Array
def to_h
if block_given?
each_with_object({}) {|a,r| k,v = yield a; r[k] = v }
else
each_with_object({}) {|(k,v),r| r[k] = v }
end
end
end
ハッシュに対して使うと配列で返るメソッドたくさんあるのにハッシュに戻すメソッド無いなんて。。。
こんな長い処理いちいち書けないでしょ。
a = [[:a,123], [:b,456], [:c,789]]
p a.to_h
#=> {:a=>123, :b=>456, :c=>789}
p a.to_h {|k,v| [k,v-(v%100)] }
#=> {:a=>100, :b=>400, :c=>700}


7.範囲内に収める

数値の上限と下限を設定したい場合、[3, [n, 9].min]].max というようにすると思います。
if文を使うには長すぎる。配列を使うのは贅沢。

Comparable#clamp
module Comparable
def clamp(min, max)
return min if self < min
return max if self > max
self
end
end
12.clamp(3, 9) #=> 9


8.XP と VX でも tap

Ace では、標準で使えるのですけど、それ以前で使いたいときは次のように定義します。

Object#tap
class Object
def tap
yield self
self
end
end
途中経過を見たいときとか。
p 123.to_s.tap {|a|p a}.chars.to_a.tap {|a|p a}.map(&:to_i)
何らかの操作を実行した後に自身を返したいときに最後に変数書かなくて良いよ。
def method
var = Something
var.property1 = 123
var.property2 = 'hoge'
var
end
# これが、こう。
def method
Something.tap do |var|
var.propaty1 = 123
var.propaty2 = 'hoge'
end
end
self 以外の値が欲しいときは break しよう!
123.tap { break 0 } #=> 0



いかがだったでしょうか?
今回は、ツクールに便利機能を移植するの回でした。
コメント




 

 ※ コメント内にURLを含めるには、バッククォート(`)をURLの直前に付け加えてください。


管理人のみ閲覧許可 [?]

素材利用報告
素材を利用させていただいたゲームを公開しましたので報告させていただきます。ありがとうございました。
`://freegame-mugen.jp/roleplaying/game_8470.html
【2020/01/18 20:49】 | 真白灰 | [編集]
トラックバック
トラックバックURL:
http://cacaosoft.blog42.fc2.com/tb.php/801-6ff253da
≪ トップページ ≫
カレンダー
03 << 2020/04 >> 05
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -

カテゴリー
最近の記事
最近のコメント
タグクラウド

リンク