2010-04-09 12 views
43

Jest odwrotnością tego pytania: Why can't strings be mutable in Java and .NET?Dlaczego Matz zdecydował się na domyślne ustawienie Ciągów w Ruby?

Czy to wybór dokonany w Ruby tylko dlatego operacje (dodaje) i takie są skuteczne na smyczki modyfikowalnych, czy też jest jakiś inny powód?

(jeśli to tylko wydajność, które wydają się osobliwe, ponieważ konstrukcja Ruby wydaje inaczej by nie umieścić wysoką premię na faciliating sprawną realizację.)

+0

Uwaga: Wiem niewiele o Ruby. Ale interesuję się projektowaniem języka. –

+4

Dlaczego nie zapytasz Matza? Prawdopodobnie ma lepszą odpowiedź niż my –

+3

@Sam: haha, dobry punkt. Mam nadzieję, że gdzieś o tym napisał, a ktoś mógłby mi o tym powiedzieć lub podsumować. –

Odpowiedz

32

Jest to zgodne z projektem Ruby, jak można zauważyć. Niezmienne ciągi są bardziej wydajne niż ciągi zmienne - mniej kopiowania, ponieważ łańcuchy są ponownie używane - ale utrudniają pracę programisty. Intuicyjnie postrzega się ciągi jako zmienne - można je łączyć ze sobą. Aby sobie z tym poradzić, Java cichutko tłumaczy konkatenację (przez +) dwóch ciągów na użycie obiektu StringBuffer i jestem pewien, że istnieją inne takie hacki. Ruby wybiera zamiast tego, aby łańcuchy były domyślnie modyfikowane kosztem wydajności.

Ruby ma również wiele metod destrukcyjnych, takich jak String#upcase!, które polegają na tym, że łańcuchy są zmienne.

Innym możliwym powodem jest to, że Ruby jest inspirowana przez Perla, a Perl używa ciągów zmiennych.

Ruby ma symbole i zamrożone struny, obie są niezmienne. Dodatkową korzyścią jest to, że symbole są unikalne na każdą możliwą wartość ciągu.

+0

OK. Ale dlaczego łańcuchy domyślnie są zmienne? Edytowałem pytanie i dodałem "domyślnie". –

+2

Można napisać ciąg niezmienny, nazywając go '.frozen', ale tak naprawdę nie można zmienić niezmiennego łańcucha, który może być modyfikowany - naruszałoby to zasadę. Na przykład, jeśli przekażę niezmienny ciąg znaków do funkcji, nie oczekiwałbym, że funkcja sprawi, że będzie on zmienny i zacznie go zmieniać. – rjh

+0

Może to być również spowodowane tym, że ciąg ruby ​​jest uważany za przeliczalny. Ciąg jest postrzegany jako "lista" znaków, naturalnym oczekiwaniem jest to, że można dodać i usunąć z listy. Wdrożenie domyślnie niepotwierdzonych łańcuchów i wciąż zastosowanie przeliczników semantycznych byłoby bolesne. – Jean

4

To są moje opinie, a nie Matza. Dla celów tej odpowiedzi, gdy mówię, że język ma "niezmienne łańcuchy", oznacza to, że jego ciągi są niezmienne, tj. Nie ma możliwości utworzenia łańcucha, który można zmienić.

  1. przycisków „stały łańcuch” widzi wzór łańcuchy jak oba identyfikatorów (na przykład jako klucz mieszających i innych zastosowań wewnętrznych VM) a struktury danych do przechowywania. Chodzi o to, że identyfikacja może być niebezpieczna. Dla mnie to brzmi jak naruszenie jednej odpowiedzialności. W Ruby mamy symbol dla identyfikatorów, więc łańcuchy mogą działać jako magazyny danych. To prawda, że ​​Ruby zezwala na łańcuchy znaków jako klucze mieszające, ale uważam, że rzadko programista zapisuje ciąg znaków w zmiennej, używa go jako klucza skrótu, a następnie modyfikuje ciąg znaków. W umyśle programisty istnieje (lub powinno być) rozdzielenie 2 zastosowań łańcuchów. Często ciąg znaków używany jako klucz skrótu jest dosłownym ciągiem znaków, więc jest niewielkie prawdopodobieństwo, że zostanie zmutowany. Używanie łańcucha jako klucza haszującego nie różni się zbytnio od używania tablicy dwóch łańcuchów jako klucza skrótu. Dopóki twój umysł dobrze rozumie, co używasz jako klucza, wtedy nie ma problemu.

  2. Posiadanie napisu jako magazynu danych jest przydatne z punktu widzenia kognitywnej prostoty. Po prostu weź pod uwagę Javę i jej StringBuffer. Jest to dodatkowa struktura danych (w już dużej i często nieintuicyjnej bibliotece standardowej), którą musisz zarządzać, jeśli próbujesz wykonywać operacje na łańcuchach, takie jak wstawianie jednego ciągu znaków do określonego indeksu innego ciągu. Z jednej strony, Java dostrzega potrzebę wykonywania tego rodzaju operacji, ale ponieważ niezmienne struny są narażone na działanie programisty, musiały wprowadzić kolejną strukturę, aby operacje były nadal możliwe bez konieczności ponownego odkrywania koła. To stawia dodatkowe obciążenie poznawcze programisty.

  3. W języku Python wydaje się, że najłatwiejszym sposobem wstawienia jest pobranie podciągu przed i po punkcie wstawiania, a następnie połączenie ich wokół ciągu, który ma zostać wstawiony. Przypuszczam, że mogliby łatwo dodać metodę do standardowej biblioteki, która wstawia i zwraca nowy ciąg.Jednakże, jeśli metoda nazywa się insert, początkujący mogą myśleć, że mutuje ciąg; aby być opisowym, musiałby on być nazwany new_with_inserted lub czymś tak dziwnym. W codziennym użyciu "wstawianie" oznacza zmianę zawartości rzeczy wstawionych do (np. Umieszczenie koperty w skrzynce pocztowej zmienia zawartość skrzynki pocztowej). Ponownie pojawia się pytanie "dlaczego nie mogę zmienić mojego magazynu danych?"

  4. Ruby zapewnia zamrożenie obiektów, dzięki czemu można je bezpiecznie ominąć bez wprowadzania drobnych błędów. Miłą rzeczą jest to, że Ruby traktuje łańcuchy tak samo, jak każdą inną strukturę danych (tablice, skróty, instancje klasy); wszyscy mogą zostać zamrożeni. Spójność jest przyjazna dla programisty. Niezmienne łańcuchy sprawiają, że łańcuchy stają się "specjalną" strukturą danych, gdy tak nie jest, jeśli używa się jej jako magazynu danych.

Powiązane problemy