2015-11-14 23 views
6

Niedawno zacząłem pracować z kodowaniem w Ruby i jestem zdezorientowany przez pewne zachowanie.String Kodowanie w Rubim

Używam 2.2.3p173 i pokazuję co następuje:

__ENCODING__    #=> #<Encoding:UTF-8> Default encoding in 2.2.3 

"my_string".encoding  #=> #<Encoding:UTF-8> 
Object.to_s.encoding  #=> #<Encoding:US-ASCII> 
Object.new.to_s.encoding #=> #<Encoding:ASCII-8BIT> 

Jaka jest przyczyna tej rozbieżności w kodowaniu?

Odpowiedz

4

Ładne znalezisko!

Krótka odpowiedź jest całkowicie dowolna i zależy od tego, w jaki sposób Ruby wewnętrznie tworzy ciągi, które są zwracane.

Istnieje cały szereg wewnętrznych funkcji C, które konstruują puste ciągi lub literalne łańcuchy z kodowaniem US-ASCII: rb_usascii_str_new i podobne. Są często używane do konstruowania ciągów przez dołączanie mniejszych fragmentów strun. Prawie każdy to_s metoda robi to:

[].to_s.encoding 
#<Encoding:US-ASCII> 
{}.to_s.encoding 
#<Encoding:US-ASCII> 
$/.to_s.encoding 
#<Encoding:US-ASCII> 
1.to_s.encoding 
#<Encoding:US-ASCII> 
true.to_s.encoding 
#<Encoding:US-ASCII> 
Object.to_s.encoding 
#<Encoding:US-ASCII> 

Więc dlaczego nie Object.new.to_s? Kluczem jest tutaj, że Object#to_s jest klasą awaryjną to_s dla klasy , więc aby uczynić ją generyczną, a jednocześnie informatywną, zakodowała ją, aby wyprowadzić wartość wewnętrznego wskaźnika obiektu. Najłatwiej to zrobić z sprintf i specyfikatorem %p. ALE Ktokolwiek zakodował zapakowanie Ruby sprintfrb_sprintf, dostał leniwego i po prostu ustaw kodowanie na NULL, które powraca do ASCII-8BIT. Więc generalnie wszystko, co zwraca sformatowany ciąg będzie mieć to kodowanie:

Object.new.to_s 
#<Encoding:ASCII-8BIT> 
nil.sort rescue $!.to_s.encoding 
#<Encoding:ASCII-8BIT> 
[].each.to_s.encoding 
#<Encoding:ASCII-8BIT> 

Jak ciągów zdefiniowanych przez skrypt, ci uzyskać domyślne kodowanie UTF-8, jak można by oczekiwać.

1

Object jest zdefiniowana w C jeśli spróbuj wykonać następujące czynności:

String(123456).encoding #=> #<Encoding:ASCII-8BIT> 
"123456".encoding  #=> #<Encoding:UTF-8> 

nie kopać dużo w kodzie źródłowym ruby ​​ale looks podoba się harcoded kodowanie (rb_usascii_str_new2) dla to_s