Семантика значений¶
Mojo не применяет конкретную семантику значений или семантику ссылок. Он поддерживает их обе и позволяет каждому типу определять, как он создается, копируется и перемещается(если вообще используется). Итак, если вы создаете свой собственный тип, вы можете реализовать его для поддержки семантики значений, ссылочной семантики или того и другого вместе. Тем не менее, Mojo разработан с учетом поведения аргументов, которые по умолчанию используют семантику значений, и обеспечивает жесткий контроль ссылочной семантики, что позволяет избежать ошибок памяти.
Элементы управления ссылочной семантикой предоставляются моделью владения значением, но прежде чем мы перейдем к синтаксису и правилам для этого, важно, чтобы вы поняли принципы семантики значений. Как правило, это означает, что каждая переменная имеет уникальный доступ к значению, и любой код, выходящий за рамки этой переменной, не может изменять ее значение.
Введение в семантику значений¶
В самой простой ситуации совместное использование семантического типа значения означает, что вы создаете копию значения. Это также известно как "передача по значению". Например, рассмотрим этот код:
def main():
var x = 1
var y = x
y += 1
print("x:", x)
print("y:", y)
x: 1
y: 2
Мы присвоили x значение y, что создает значение для y путем создания копии x. Когда мы увеличиваем y, значение x не меняется. Каждая переменная обладает исключительным правом собственности на значение.
Принимая во внимание, что если тип вместо этого использует ссылочную семантику, то y будет указывать на то же значение, что и x, и увеличение любого из них повлияет на значение для обоих. Ни x, ни y не будут "владеть" значением, и любой переменной будет разрешено ссылаться на него и изменять его.
Числовые значения в Mojo являются семантическими, поскольку они представляют собой тривиальные типы, которые легко скопировать.
Семантика значений в функциях Mojo¶
Семантика значений также применяется к аргументам функций в Mojo по умолчанию. Однако способ их применения отличается в зависимости от соглашения об использовании аргументов, которое обсуждается на странице Владения.
Например, в следующей функции аргумент y по умолчанию является неизменяемым, поэтому, если функция хочет изменить значение в локальной области видимости, ей необходимо создать локальную копию:
fn add_two(y: Int):
# y += 2 # это привело бы к ошибке компилятора, потому что `y` является неизменяемым
# Вместо этого мы можем сделать явную копию:
var z = y
z += 2
print("z:", z)
def main():
var x = 1
add_two(x)
print("x:", x)
z: 3
x: 1
Все это согласуется с семантикой значений, поскольку каждая переменная сохраняет уникальное право собственности на свое значение.
Способ, которым функция получает значение y, - это подход к семантике значений "смотри, но не трогай". Это также более экономичный с точки зрения памяти подход при работе с аргументами, требующими больших затрат памяти, поскольку Mojo не создает никаких копий, если мы сами явно не создаем копии.
Таким образом, поведение аргументов функции по умолчанию является полностью семантическим по значению: аргументы являются неизменяемыми ссылками, и функция не влияет на любую живую переменную вызывающего объекта.
Но мы также должны разрешить ссылочную семантику (изменяемые ссылки), потому что именно так мы создаем эффективные и экономичные с точки зрения памяти программы (копирование всего обходится очень дорого). Задача состоит в том, чтобы внедрить ссылочную семантику таким образом, чтобы не нарушить предсказуемость и безопасность семантики значений.
В Mojo мы делаем это следующим образом: вместо того, чтобы гарантировать, что каждая переменная имеет "эксклюзивный доступ" к значению, мы гарантируем, что у каждого значения есть "эксклюзивный владелец", и уничтожаем каждое значение, когда заканчивается срок службы его владельца.
На следующей странице, посвященной владению значением, вы узнаете, как изменить соглашения об аргументах по умолчанию и безопасно использовать ссылочную семантику, чтобы у каждого значения одновременно был только один владелец.