«Изменчивость» имеет смысл только тогда, когда вы говорите о каком-то составном типе, о чем-то, что имеет «внутренние» части, которые, возможно, можно изменить независимо от того, что в нем содержится. Строки естественным образом состоят из символов, и в языке нет механизма, который позволял бы нам изменять символ в существующей строке, кроме назначения целой новой строки, поэтому мы говорим, что она неизменна.
Для int не имеет смысла говорить об изменчивости, потому что, каковы "компоненты" int? Вы изменяете int, назначая совершенно новый int, но назначение не считается "мутирующим".
Существует некоторая связь между проблемами изменчивости и ссылочных типов. Семантически нет никакой разницы между неизменным ссылочным типом и типом значения. Зачем? Предположим, что int на самом деле был указателем на неизменяемый объект (т.е. *InternalIntObject
без функций для изменения InternalIntObject
). Как только вы назначите такой указатель на переменную, он всегда будет представлять одно и то же целочисленное значение (не может быть изменено другими, которые совместно используют один и тот же объект), поскольку объект является неизменным. Это то же самое поведение, что и тип целочисленного значения. Вы можете назначить целые числа оператором присваивания; также вы можете назначить эти указатели по назначению; результат будет таким же: назначенная переменная представляет собой то же целое число, что и то, чему она была назначена. Единственным отличием будет сравнение, и арифметические операторы придется переопределять, чтобы отменить ссылку на указатель для вычисления результата.
Поэтому изменчивость имеет смысл только для ссылочных типов.
Что касается того, что вы просили, то «изменяемые» типы обычно считаются ссылочными типами, кроме строки: карты, каналы, срезы (относительно данных, на которые указывает срез), а также указатели на что-либо (так как Вы можете изменить значение в месте, указанном указателем).