2013-04-30 11 views
6

Właśnie odkryłem następujące dziwne zachowanie z String#split:Dlaczego split (") próbuje być (zbyt) inteligentny?

"a\tb c\nd".split 
=> ["a", "b", "c", "d"] 

"a\tb c\nd".split(' ') 
=> ["a", "b", "c", "d"] 

"a\tb c\nd".split(/ /) 
=> ["a\tb", "c\nd"] 

The source (string.c od 2.0.0) ma długość ponad 200 linii i zawiera fragment takiego:

/* L 5909 */ 
else if (rb_enc_asciicompat(enc2) == 1) { 
    if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){ 
     split_type = awk; 
    } 
} 

Później w kodzie dla typu podziału awk, rzeczywisty argument nie jest już używany i robi to samo, co zwykły split.

  • Czy ktoś jeszcze czuje, że jest w jakiś sposób zepsuty?
  • Czy istnieją ku temu uzasadnione powody?
  • Czy "magia" tak się zdarza częściej niż większość ludzi może myśleć w Ruby?
+0

Dlaczego coś, co zostało udokumentowane, jest "zbyt inteligentne"? Jest to domyślne domyślne zachowanie, które można przesłonić, jeśli wybierzesz, przekazując mu alternatywny wzorzec do podziału tekstu. –

+0

Zbyt inteligentne mam na myśli domysły Ruby, które chcę podzielić na wszystkie znaki odstępu, w których dosłownie mówię, żeby dzieliły się w przestrzeniach. –

+0

Zamierzam głosować, aby zamknąć to pytanie, ponieważ zdaję sobie sprawę, że prawdopodobnie nie ma ogólnej, satysfakcjonującej odpowiedzi na to pytanie. Dziękuję za wszystkie odpowiedzi i komentarze! –

Odpowiedz

4

Jest to zgodne z zachowaniem Perla: split(). Co z kolei opiera się na Gnu awk'ssplit(). Jest to więc długa tradycja z początkami w systemie Unix.

Od perldoc na split:

W innym szczególnym przypadku, Split emuluje zachowanie domyślne polecenia narzędzie wiersza awk gdy wzór jest albo pominięte lub dosłownego ciąg składający się z jednego znaku spacji (takie jak "" lub "\ x20", , ale nie np.//). W tym przypadku wszelkie początkowe spacje w wyrażeniu EXPR wynoszą usunięte przed dzieleniem, a WZORZEC jest traktowany jako , jeśli był to/\ s + /; w szczególności oznacza to, że każda ciągła spacja (nie tylko pojedynczy znak spacji) jest używana jako separator. Można jednak uniknąć tej szczególnej obróbki, podając wzór zamiast ciągu "", umożliwiając w ten sposób separator tylko pojedynczemu znakowi spacji .

+1

Grałem trochę z rozłamem Perla i zauważyłem, że ma to sens w Perlu, ponieważ potrzebuje argumentu. Pusty ciąg nie działałby, ponieważ jest to inny specjalny przypadek (zwraca tablicę znaków, jak w rubinie). Najbliższą rzeczą do wywołania split bez argumentów w Perlu było 'split (undef, $ str)', ale faktycznie zachowuje się jak 'split ('', $ str)', a nie 'split ('', $ str)' myślę, że to nie jest całkiem spójne :). W końcu kłócili się, dlaczego rzeczy są takie i że w Perlu robiono już zbyt często, więc zatrzymam się tutaj :) –

+0

Twoja odpowiedź jest nadal najlepsza, więc ją zaakceptuję. Dzięki! –

+0

Interesująca historia. – davogones

2

Sprawdź documentation, ta część, w szczególności:

Jeśli wzór jest ciągiem znaków, wtedy jego zawartość są wykorzystywane jako ogranicznik gdy podział ul. Jeśli wzorzec jest pojedynczym odstępem, str jest podzielony na białe spacje , zignorowane znaki początkowe i ciągłe sąsiednich białych znaków.

Jeśli wzorzec zostanie pominięty, wartość $; Jest używane. Jeśli $; is nil (domyślnie jest to ), str jest podzielony na białe znaki tak jakby podano `.

Możesz użyć wyrażenia regularnego, aby podzielić ciąg znaków.

+0

Dzięki! Przeczytałem dokumentację. Moje pytanie brzmi bardziej: "Czy powinniśmy to naprawić, czy może mamy ku temu dobry powód?". –

+0

Przynajmniej wiemy, że jest to zamierzone. Możemy spróbować znaleźć powód, dla którego tak zaprojektował Matz, i możemy również twierdzić, że jest to dziwne. Ale nie możesz "pójść i naprawić". Kto decyduje, to Matz. – sawa

+0

Oczywiście Matz decyduje o przyszłości MRI. Ale wciąż możemy podejść do niego o możliwe poprawki;) –