Модель памяти
Все значения ссылочные, создаются в памяти 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 синхронизируется автоматически, поэтому ручную синхронизацию не нужно использовать.