実際にはFlutter/Dartで遭遇したのだけど、親言語であるJavaScriptの挙動を引き継いでいるだろうということで。
例えば単純なカンマ区切りの文字列(エスケープやカンマを含まない)があったとして、
const csvString = 'a,b,c' |
文字列の split
メソッドでで分割できて、個数もわかる:
const elems = csvString.split(',') // => [ 'a', 'b', 'c' ] |
これを空文字列に対して行うと空文字列が1つの配列が返ってしまい、個数は1となり、想定と異なってしまう:
const emptyString = '' |
自分の感覚では空配列が返るものだと思いこんでいたので、思いっきりバグを仕込んでしまっていた。
リファレンス
String.prototype.split() - JavaScript | MDN
註: 文字列が空であるとき、
split
メソッドは、空の配列ではなく、1 つの空文字列を含む配列を返します。文字列とseparator
が両方とも空の文字列の場合、空の文字列が返されます。
仕様ですか…。
各言語を調べてみる
空配列が返る:
空文字列を含む1要素の配列が返る:
数で正当性を訴えて「やっぱJavaScript変だよね」という論調にならないかと調べてみたが、圧倒的に完敗…!
質問箱
The confusion about the split() function of JavaScript - Stack Overflow
consistency とはいうけど、空配列を返すのが一貫しているように思うのだが…(各要素が空文字列じゃないとすると)。
要素が空のことを空文字列で表しているのがいけないのか?
空要素の場合は空文字列じゃなく null
で表現するとしてみる。
扱いは面倒になるが、それはそれで理にかなっている気がする。
joinの逆演算として考える
split
を join
の演算として考えるとどうか。
> ['1','2','3'].join(',') |
別に一貫してるよね!?
ただこれも空文字列を許すとなると [''].join(',')
も ''
なので 、デザインの違いになってしまうのか…?