Для улучшения ясности в выражении цели кода и выявления ошибок в языке различаются некоторые разновидности состояния переменной. Эти состояния не изобретаются языком. Роль языка лишь в явном отслеживании того, что существует вне зависимости от него. В других языках эта характеристика тоже может отслеживаться, но обычно в меньшей степени (например, только неизменяемость).
Следует учитывать, что статическая и динамическая характеристики могут не совпадать вследствии циклов и ветвлений. Кроме того, противоположные характеристики значения, которые не могут совпадать в переменной во времени, то есть динамически, статически могут присутстсвовать в одном месте кода в качестве возможности вследствии неопределённости.
Состояние переменной не является характеристикой исполнения. Нет конструкций языка для опроса переменной о её состоянии. И хотя оно может проверяться при выполнении для обнаружения неправильности кода некоторыми исполнителями, это не гарантируется. Простая часть проверок обеспечивается надёжно при трансляции кода, а второстепенная — лишь с некоторой вероятностью в зависимости от возможностей исполнителя языка.
- По возможности менять значение
- Неизменяемое значение
- Запрещённое для изменения значения в контексте
- Не запрещённое для изменения
- По очевидности значения
- Известное значение
- Неизвестное
- По использованию значения
- Прочитанное значение
- Неиспользованное значение
- По широте множества значения
- Нормальное значение — значение в границах применимости типа-основы, полученное без ошибок кода
- Неявно ограниченное
- Произвольное значение исходного типа
- Без значения
- Не выставлено начальное значение
- Значение устранено в результате его односторонней передачи или закрытия
- Ошибочное значение, полученное как следствие проявление ошибки в коде.
- По защите значения от утечки
- Незащищённое по умолчанию
- Защищённое по явному указанию
- По уникальности значения
- Гарантируется, что значение уникально в указанном контексте
- Значение может быть не уникально
- Значение, изолированное в графе
По изменяемости
Неизменяемое значение переменной в данном контексте задаётся типом и обозначает не только то, что код в рамках контекста не может его менять, но и то, что никакой код не может, как минимум, пока контекст актуален. Неизменяемые значения важны с точки зрения сохранения неизменных свойств и владения общими данными. Переменные с неизменяемыми значениями могут быть изменяемыми в режиме начализации.
Переменная с запретом на изменение значения не позволяет коду, находящемуся ниже в той же ветви, где произведён запрет, изменять значение переменной. Но изменение может происходить повторно внутри цикла в месте запрета или выше, а также в соседних ветвях. Если это ссылочный параметр, то он также может быть изменён кодом вне подпрограммы при его прямом или косвенном вызове (следует уточнить это).
В понимании языка переменные, не запрещённые для изменения значения, действительно не препятствуют изменениям значений в переменной. Тем не менее это понятие не тождественно переменным, разрешённым для изменения, так как код может фактически не изменять значение и требовать этого для правильности кода, но программист мог счесть излишним это указывать. При этом язык всё же не включает явно устанавливаемого разрешения как несколько избыточного. Если это будет нужно, его можно добавить позже.
По очевидности значения
Известное значение в переменной возникает, когда ей присваивают постоянную. Косвенное использование постоянных через переменную в таком состоянии является нежелательным кодом.
По использованию
Значение из переменной в итоге может быть не использовано, что считается ошибкой, если код ни при каких обстоятельствах не подразумевает его прочтения. Если значение действительно не нужно, что может произойти, например, при получении второстепенного значения из некой процедуры, то вместо объявленной переменной лучше использовать предопределённое имя unused. Но если выходное значение не было помечено, как дозволенное для пропуска, то это имя недопустимо.
По множеству значений
Нормальное значение может быть произвольным или ограниченным, явно или неявно.
Зачастую, основной тип переменной указывается достаточно грубо, избыточно широко задавая множество возможных значений, в то время как действительное множество у́же. Но сверхстрогое указание типа, что было бы полезно с точки зрения доказательства правильности кода, требует слишком больших усилий, поэтому не может быть обязательным в прагматичном языке. Тем не менее, по умолчанию это более узкое подмножество подразумевается неявно, что важно для анализа кода. Но в ряде случаев важно подчеркнуть, что указываемый тип не является приблизительным, а действительно задаёт всё поразумеваемое за ним множество. Например, это характерно для вводимых данных и генераторов псевдослучайных чисел.
Первоначально, произвольность значения задаётся уточнением типа переменной — приставкой any
, но также произвольность можно передать с помощью части выражений. С другой стороны произвольность снимается в ветвлении после применения в логических выражениях. Также произвольность может исчезать в некоторых выражениях, например, при делении произвольного значения.
Утверждения являются явным выражением того, что используемые в них значения переменных не являются произвольными, поэтому произвольность и утверждения несовместимы. Произвольные значения нельзя использовать в утверждениях и в других местах, в которых истинная произвольность может привести к ошибке. Например, произвольный индекс может выходить за пределы массива. Нельзя делить на произвольное значение, ведь делитель может быть равен 0.
Отсутствие значения у переменной означает лишь отсутствие явно заданного значения. Чтение переменной в этом состоянии считается ошибочным состоянием.
Также язык не подразумевает существование специального значения по умолчанию, подобного автоматическому занулению, хотя это и может обеспечиваться некоторыми исполнителями. Использование в выражениях переменных без значения считается ошибочным состоянием.
По защите значения от утечки
Пометка переменных с помощью слова sensitive
, как хранящих охраняемые от утечек данные, приводит не только к отслеживанию передачи в неохраняемые места, но и к особому обращению с такими переменными. Это отличает характеристику sensitive от остальных характеристик, для которых поддержка времени исполнения является необязательной. Охраняемые переменные автоматически очищаются при выходе из обращения или при явном указании потери значения. Если ОС позволяет, то такие данные не сохраняются на накопитель из-за необходимости выгрузки данных из оперативной памяти.
По уникальности значения
Эта характеристика отслеживается только для переменных указательного типа. Первоисточником гарантий уникальности значения указателя является подпрограмма выделения динамической памяти при условии, что действие происходит после проверки, что выделение произошло успешно. Дальнейшие гарантии происходят из отслеживания перемещений уникальных значений, для чего нужны перемещающие присваивания. Для простоты отслеживания обычные присваивания, создающие копии значений, снимают со значения гарантию уникальности, даже если фактическая уникальность восстанавливается в последующих присваиваниях, когда, например, одна из переменных получает другое значение.
Уникальный указатель-граф перемещающим присваиванием можно передать другому потоку или в переменную с неизменямым значением.
Значение может быть не уникальным, но появляться исключительно внутри одного графа. Благодаря изоляции локально неуникальное значение не препятствует возможности передачи графа с сохранением его уникальноси. Соблюдение изолированности значения отслеживается групповым образом — до тех пор пока группа оказывается изолированным графом, подтверждается изолированность содержащихся в нём значений. Не нарушают изолированности графа:
- Присваивания внутри графа, для чего нужно использовать внутриструктурные присваивания
- Присваивания элементам графа nil или других уникальных графов с перемещением