rubyのRange#include のstringが特殊なケースを除いてString#uptoを呼び出しているため遅い
rb_str_include_range_p@string.c
を呼び出すrb_str_upto_each
を呼び出しているrangeの始端もしくは終端にUTF-8文字が含まれると非自明な挙動をする
("a".."あ").to_a #=> ["a", ... , "zzy", "zzz"]
[*"z".."aa"] #=> []
[*"a"..."z"] + [*"z".."aa"] == [*"a".."aa"]
になるのが自然だが、[*"z".."aa"]
が空になるためこれは一致しない(c..a)
のようなものにイテレーションを走らせないようにした結果,このように到達できるものもはじいてしまっている("aa"..).include?("b") #=> true
(0..1).include?(0.5) #=> true
String#succ のアルゴリズム
str_succ
enc_succ_alnum_char
を使うenc_succ_char
を使うenc_succ_alnum_char
max_gaps
によって定められる)enc_succ_char
enc_pred_char
enc_succ_char
の逆enum neighbor_char
NEIGHBOR_NOT_CHAR
NEIGHBOR_FOUND
NEIGHBOR_WRAPPED
enc_succ_alnum_char
だと「次が文字として無効だったから巻き戻せるところまで巻き戻したよ」みたいな意味enc_succ_char
だとバイト長が変わったみたいな意味?("b".."aa")
のような単純な辞書順比較によって正しく評価されていなかったrangeが正しく評価されるようになる
("b".."aa").to_a => []
になる問題もこれで解決できるRange#include?
String#upto
で全列挙していた実装の代わりに本methodを使うことで判定が高速に行えるようになる ("b".."aa").include?("z")
, ("b"..).include?("aa")
などの辞書順比較を用いていたことによるバグが直るCに移植
ascii_str_reachable_p
rb_str_upto_each
rb_str_include_range_p
range_include_internal
メモ
matz: I will merge this PR after updating master by mruby3 branch.
String#[] with Range
String#[]= with Range
がなかったので生やしたEnumerable#take
など各種メソッドMRB_WITHOUT_FLOAT
でコンパイルが通らない
Range#to_s
, Range#inspect
nil.to_s
は空文字になるので結果的に Range#to_s
改変の必要はない('b'..'d').include?('ba')
の挙動が ruby と mruby で異なる問題がある // TODORange#{max, last}
('a'..'z').size # => nil
Range
Array#[]
, Array#[]=
String#[] with Range
Enumerable#take
MRB_WITHOUT_FLOAT
すると落ちる('b'..'d').include?('ba') # => false
(9223372036854775807..9223372036854775808).each
が壊れる
integral_div()@numeric.c
でMRB_WITHOUT_FLOAT
ありでビルドするとmrb_fixnum_value()
への引数の数がおかしいので落ちる。("a"..).each{|c| p c}
rb_str_upto
およびこれのメインロジックに相当するrb_str_upto_each
とは別にendless用にrb_str_upto_endless_each
を用意している.String#upto
を使っているString#upto
の第一引数endに nil
を渡すことを許容する
__
prefixつきのメソッドをprivateとして実装しているものがあるためこれを踏襲する(使えてはしまうが)
__sub_replace@string.rb
など_
の数は1個だったり2個だったりする(え?)mrb_range_beg_len()@range.c
)mrb_range_beg_len()@range.c
)Range#to_s
, Range#inspect
Range
Array#[]
, Array#[]=
String#[]
, String#[]=
チームとしての作業
ネタ探し
Range.new
だけならnilチェックだけでいいだろうけど、``1..`のような場合)一旦、mrubyにendless rangeを移植することを目標とすることにした
各々、RubyとmRubyのRange周りの実装をリーディング
個人作業
チームとしての作業
個人作業
水橋
/usr/include
が無い問題はcommand line toolsのものを認識させてあげればよく( /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include
とかにありそう),これは export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)"
で解決する(いつもの).橋本
三浦