Какой смысл в том, что некоторые типы неизменяемы, а другие нет?
Без некоторых изменчивых типов, вам бы пришлось пойти на чистую свиньюфункциональное программирование - совершенно другая парадигма, чем ООП и процедурные подходы, которые в настоящее время наиболее популярны, и, хотя они чрезвычайно мощны, по-видимому, очень сложны для многих программистов (что происходит, когда вам do нужны побочные эффекты вязык, в котором нет ничего непостоянного, а в реальном программировании, конечно, вы неизбежно это делаете, является частью проблемы - например, Monads на Haskell - это очень элегантный подход, но сколько программистов вы знаете?которые полностью и уверенно понимают их и могут использовать их так же, как и типичные конструкции ООП? -).
Если вы не понимаете огромной ценности наличия нескольких парадигм (как FP one , так и * 1014)* те, которые в основном полагаются на изменчивые данные), я рекомендую изучить шедевр Хариди и Ван Роя, Концепции, методы и модели компьютерного программирования - "a SICP для 21-го века", как я однажды описал это; -).
Большинство программистов,знакомы ли они с Хариди и Ван Роем или нет, с готовностью признают, что для них важно иметь как минимум некоторые изменяемые типы данных.Несмотря на предложение, которое я цитировал выше из вашего Q, которое принимает совершенно иную точку зрения, я полагаю, что это также может быть корнем вашей растерянности: не «почему некоторые из каждого», а скорее «почему некоторые immutables at all ".
Подход" полностью изменяемый "был однажды (случайно) получен в реализации на Фортране.Если бы у вас было, скажем,
SUBROUTINE ZAP(I)
I = 0
RETURN
, то программный фрагмент, например,
PRINT 23
ZAP(23)
PRINT 23
напечатал бы 23, тогда 0 - число 23 былобыл изменен, поэтому все ссылки на 23 в остальной части программы на самом деле ссылались бы на 0. Технически, это не ошибка компилятора: у Fortran были тонкие правила относительно того, что представляет собой ваша программа, и ей запрещено делать передачу констант против переменных.к процедурам, которые присваивают их аргументы, и этот фрагмент нарушает эти малоизвестные, не обязательные для исполнения правила, так что это не программа, а компилятор.На практике, конечно, количество ошибок, вызванных этим способом, было неприемлемо высоким, поэтому типичные компиляторы вскоре переключались на менее разрушительное поведение в таких ситуациях (помещая константы в сегменты только для чтения, чтобы получить ошибку времени выполнения, если ОС поддерживала это, илипередача свежей копии константы, а не самой константы, несмотря на накладные расходы и т. д.), хотя технически они были программными ошибками, позволяющими компилятору отображать неопределенное поведение довольно "правильно" ;-).
Альтернатива, применяемая в некоторых других языках, состоит в том, чтобы добавить усложнение нескольких способов передачи параметров - особенно в C ++, например, с помощью значения-значения, ссылки-ссылки, константы-ссылки, указателя,постоянный указатель, ... и затем, конечно, вы видите программистов, сбитых с толку объявлениями, такими как const foo* const bar
(где самый правый const
в основном не имеет значения, если bar
является аргументом для некоторой функции ... но имеет решающее значение, если bar
является локальной переменной ...! -).
На самом деле Алгол-68, вероятно, пошел дальше в этом направлении (если вы можете иметь значение и ссылку, почему бы не ссылка на ссылку?или ссылка на ссылку на ссылку?& c - Algol 68 не накладывает на это никаких ограничений, и правила для определения того, что происходит, являются, пожалуй, самым тонким, самым сложным сочетанием, когда-либо существовавшим в языке программирования «предназначенный для реального использования»).Ранний C (который имел только by-value и by-явный указатель - без const
, без ссылок, без осложнений) был, без сомнения, частично реакцией на него, как и оригинальный Паскаль.Но const
вскоре закрался, и осложнения снова начали нарастать.
Java и Python (среди других языков) прорезают эту чащу мощным мачете простоты: передача всех аргументов, и все присваивания, "по ссылке на объект" (никогда не ссылается на переменную или другоессылка, никогда не семантически неявные копии и т. д.).Определение (по крайней мере) чисел как семантически неизменных сохраняет здравомыслие программистов (а также этот драгоценный аспект простоты языка), избегая таких «упущений», как те, что были продемонстрированы в вышеприведенном коде Фортрана.
Рассматривая строки как простые примитивыкак числа вполне соответствуют предполагаемому высокому семантическому уровню языков, потому что в реальной жизни нам нужно нужны строки, которые столь же просты в использовании, как числа;альтернативы, такие как определение строк в виде списков символов (Haskell) или массивов символов (C), создают проблемы как для компилятора (сохраняя эффективную производительность при такой семантике), так и для программиста (фактически игнорируя эту произвольную структуру, чтобы сделать использование строк простымпримитивы, как часто требуется в реальной жизни).
Python пошел немного дальше, добавив простой неизменяемый контейнер (tuple
) и связав hashing с «эффективной неизменяемостью» (которая избегает определенныхсюрпризы для программиста, которые встречаются, например, в Perl, с его хешами, допускающими изменяемые строки в качестве ключей) - а почему бы и нет?Если у вас есть неизменность (драгоценная концепция, которая избавляет программиста от необходимости изучать N различных семантик для присваивания и передачи аргументов, когда N имеет тенденцию к увеличению со временем ;-), вы также можете извлечь из этого все возможное ;-).