Почему Matz решил сделать строки изменяемыми по умолчанию в Ruby? - PullRequest
43 голосов
/ 09 апреля 2010

Это обратный вопрос: Почему строки не могут быть изменяемыми в Java и .NET?

Этот выбор был сделан в Ruby только потому, что операции (добавления и т. Д.) Эффективны с изменяемыми строками, или была какая-то другая причина?

(Если бы это была только эффективность, это могло бы показаться странным, так как дизайн Ruby, по-видимому, не слишком важен для обеспечения эффективной реализации.)

Ответы [ 2 ]

32 голосов
/ 09 апреля 2010

Это соответствует дизайну Руби, как вы заметили. Неизменяемые строки более эффективны, чем изменяемые строки - меньше копирование, так как строки используются повторно, но усложняют работу для программиста. Интуитивно понятно, что строки могут быть изменяемыми - вы можете объединить их вместе. Чтобы справиться с этим, Java тихо переводит конкатенацию (через +) двух строк в использование объекта StringBuffer, и я уверен, что есть и другие подобные хаки Вместо этого Ruby выбирает сделать строки изменяемыми по умолчанию за счет производительности.

В Ruby также есть ряд деструктивных методов, таких как String#upcase!, которые полагаются на изменчивость строк.

Другая возможная причина в том, что Ruby вдохновлен Perl, и Perl использует изменяемые строки.

В Ruby есть символы и замороженные строки, которые являются неизменяемыми. В качестве дополнительного бонуса символы гарантированно будут уникальными для каждого возможного значения строки.

5 голосов
/ 09 мая 2013

Это мои мнения, а не Мэтца. Для целей этого ответа, когда я говорю, что в языке есть «неизменяемые строки», это означает, что all его строки являются неизменяемыми, то есть нет способа создать изменяемую строку.

  1. Конструкция «неизменяемой строки» рассматривает строки как идентификаторы (например, как ключи хеш-функции и другие виды внутреннего использования VM), так и структуры хранения данных . Идея состоит в том, что идентификаторы опасны для изменчивости. Для меня это звучит как нарушение единоличной ответственности. В Ruby у нас есть символ для идентификаторов, поэтому строки могут выступать в качестве хранилищ данных. Это правда, что Ruby допускает строки в качестве хеш-ключей, но я думаю, что программист редко сохраняет строку в переменной, использует ее в качестве хеш-ключа, а затем изменяет строку. По мнению программиста, есть (или должно быть) разделение на 2 использования строк. Часто строка, используемая в качестве хеш-ключа, является литеральной строкой, поэтому существует небольшая вероятность ее мутации. Использование строки в качестве хеш-ключа мало чем отличается от использования массива из двух строк в качестве хеш-ключа. Пока ваш разум хорошо разбирается в том, что вы используете в качестве ключа, проблем не будет.

  2. Наличие строки в качестве хранилища данных полезно с точки зрения когнитивной простоты. Просто рассмотрите Java и его StringBuffer. Это дополнительная структура данных (в уже большой и часто не интуитивно понятной стандартной библиотеке), которой вы должны управлять, если вы пытаетесь выполнять строковые операции, такие как вставка одной строки по определенному индексу другой строки. Таким образом, с одной стороны, Java признает необходимость выполнения операций такого рода, но поскольку неизменяемые строки представляются программисту, им пришлось ввести другую структуру, чтобы операции все еще были возможны, не заставляя нас заново изобретать колесо. Это создает дополнительную когнитивную нагрузку на программиста.

  3. В Python кажется, что самый простой способ вставить это взять подстроки до и после точки вставки, а затем объединить их вокруг строки, которая будет вставлена. Я полагаю, они могли бы легко добавить метод в стандартную библиотеку, который вставляет и возвращает новую строку. Однако, если метод называется insert, начинающие могут подумать, что он изменяет строку; чтобы быть описательным, его нужно назвать new_with_inserted или что-то странное в этом роде. В повседневном использовании «вставка» означает, что вы изменяете содержимое вставляемых вещей (например, вставка конверта в почтовый ящик изменяет содержимое почтового ящика). Опять же, возникает вопрос: «Почему я не могу изменить свое хранилище данных?»

  4. Ruby обеспечивает замораживание объектов, поэтому их можно безопасно передавать, не внося незначительных ошибок. Приятно то, что Ruby обрабатывает строки как любую другую структуру данных (массивы, хэши, экземпляры классов); все они могут быть заморожены. Согласованность удобна для программистов. Неизменяемые строки делают строки выделяющимися как «особая» структура данных, если это не так, если вы используете ее в качестве хранилища данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...