Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Модель памяти

Все значения ссылочные, создаются в памяти heap. Удаление неиспользуемых значений при помощи GC.

Передача параметров всегда по ссылке, передаваемые последовательности всегда неизменяемые. В случае ленивой передачи параметров (“по значению”) компилятор автоматически оборачивает код в анонимную функцию, которую и передаёт по ссылке.

Возможно, что в будущем базовые типы из libretto/num без кардинальности будут создаваться на стеке и передаваться по значению. Сейчас такого поведения нет.

libretto/lazy/value - глобальные объекты

todo - переписать, уточнив терминологию

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

Есть экземпляры структур без полей. Но именно отсутствие полей не позволяет использовать их в качестве глобальных переменных (нет состояния).

Но можно привязать значение к экземпляру структуры без полей при помощи метода value из библиотеки libretto/lazy, что позволяет получить частичную замену глобальным переменным.

Метод value принимает два значения. Первое - это экземпляр структуры строго без полей. Этот объект служит идентификатором глобального значения, из разных точек программы использование одного глобального объекта обозначает работу с одной сущностью.

Второе значение - это код, который будет вызываться для инициализация значения, привязанного к глобальному объекту.

Метод value возвращает значение, если оно уже привязано к указанному глобальному объекту, либо вызывает код инициализации, результат которого привязывается к указанному глобальному объекту и возвращается из метода.

Пример:

use libretto/lazy

struct Test

def test = lazy/value(Test()): {
  println("Init")
  123
}

def main = {
  println: test
  println: test
}

Выдает:

Init
123
123

В данном примере привязка значения к Test() осуществляется один раз - при первом вызове test, когда вызывается переданный в value код инициализации. При повторном вызове test значение уже привязано, поэтому используется именно оно без вызова кода инициализации.

Важное отличие от обычных глобальных переменных в том, что момент инициализации может происходить несколько раз на усмотрение компилятора. Например, в веб-приложении значение сбрасывается и привязывается заново при изменении исходных текстов. Это нужно обязательно учитывать.

Поскольку привязанное значение может быть использовано из разных потоков, то либо это должно быть неизменяемое значение, либо работа с ним должна быть синхронизирована вручную (например, при помощи synchronized из libretto/util).

Сам вызов value синхронизируется автоматически, поэтому ручную синхронизацию не нужно использовать.