LINUX.ORG.RU

История изменений

Исправление vertexua, (текущая версия) :

Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.

в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него

Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager в какие-то асинхронные лямбды.

Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.

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


struct Client<'a> {
  x: &'a FooManager;
}

impl Client {
  fn use_x(self) {
    self.x.call();
  }
}

Client живет время 'a, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client, им владеет кто угодно другой, но живет он как минимум нужное время.

Это накладывает сразу ограничения на весь код, который создает FooManager и Client, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.

let fm = FooManager{};

let client = Client{x: &fm}; // fm живет дольше client.

// Сначала невидимое освобождение client, только потом FooManager.

Лайфтаймы еще помогают в сигнатурах функций

fn process(a &str, b: &str) -> &str {
...
}

Тут не совсем ясно, мы одалживаем две строки, и возвращаем тоже ссылку на какую-то одолженую строку… Еее явно не создали внутри, так как все собственники внутри умерли по выходу из фунции. Стало быть это a, b или их подстроки. Но какие?

fn process<'x>(a &'x str, b: &str) -> &'x str {
...
}

Все, расходимся, это кусок a.

Это важно в лапше вроде такой

let a = String::new("a");
let b = String::new("b");
let result = process(&a, &b); 
// Тут мы вроде бы вернули a, b, но секретно ссылаемся на a внутри result.
i_eat_variables(a); // Ошибка компиляции. Тут единолично хотят украсть владение над a, переместить ее
i_eat_variables(b); // Кстати вот тут ошибки не было бы.

println("{}", result);

Исправление vertexua, :

Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.

в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него

Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager в какие-то асинхронные лямбды.

Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.

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


struct Client<'a> {
  x: &'a FooManager;
}

impl Client {
  fn use_x(self) {
    self.x.call();
  }
}

Client живет время 'a, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client, им владеет кто угодно другой, но живет он как минимум нужное время.

Это накладывает сразу ограничения на весь код, который создает FooManager и Client, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.

let fm = FooManager{};

let client = Client{x: &fm}; // fm живет дольше client.

// Сначала невидимое освобождение client, только потом FooManager.

Лайфтаймы еще помогают в сигнатурах функций

fn process(a &str, b: &str) -> &str {
...
}

Тут не совсем ясно, мы одалживаем две строки, и возвращаем тоже ссылку на какую-то одолженую строку… Еее явно не создали внутри, так как все собственники внутри умерли по выходу из фунции. Стало быть это a, b или их подстроки. Но какие?

fn process<'x>(a &'x str, b: &str) -> &'x str {
...
}

Все, расходимся, это кусок a.

Это важно в лапше вроде такой

let a = String::new("a");
let b = String::new("b");
let result = process(&a, &b); 
// Тут мы вроде бы вернули a, b, но секретно ссылаемся на a внутри result.
i_eat_variables(a); // Ошибка компиляции.
i_eat_variables(b); // Кстати вот тут ошибки не было бы.

Исправление vertexua, :

Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.

в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него

Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager в какие-то асинхронные лямбды.

Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.

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


struct Client<'a> {
  x: &'a FooManager;
}

impl Client {
  fn use_x(self) {
    self.x.call();
  }
}

Client живет время 'a, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client, им владеет кто угодно другой, но живет он как минимум нужное время.

Это накладывает сразу ограничения на весь код, который создает FooManager и Client, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.

let fm = FooManager{};

let client = Client{x: &fm}; // fm живет дольше client.

// Сначала невидимое освобождение client, только потом FooManager.

Лайфтаймы еще помогают в сигнатурах функций

fn process(a &str, b: &str) -> &str {
...
}

Тут не совсем ясно, мы одалживаем две строки, и возвращаем тоже ссылку на какую-то одолженую строку… Еее явно не создали внутри, так как все собственники внутри умерли по выходу из фунции. Стало быть это a, b или их подстроки. Но какие?

fn process<'x>(a &'x str, b: &str) -> &'x str {
...
}

Все, расходимся, это кусок a.

Исправление vertexua, :

Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.

в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него

Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager в какие-то асинхронные лямбды.

Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.

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


struct Client<'a> {
  x: &'a FooManager;
}

impl Client {
  fn use_x(self) {
    self.x.call();
  }
}

Client живет время 'a, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client, им владеет кто угодно другой, но живет он как минимум нужное время.

Это накладывает сразу ограничения на весь код, который создает FooManager и Client, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.

let fm = FooManager{};

let client = Client{x: &fm}; // fm живет дольше client.

// Сначала невидимое освобождение client, только потом FooManager.

Лайфтаймы еще помогают в сигнатурах функций

fn process(a &str, b: &str) -> &str {
...
}

Тут не совсем ясно, мы одалживаем две строки, и возвращаем тоже ссылку на какую-то одолженую строку… Еее явно не создали внутри, так как все собственники внутри умерли по выходу из фунции. Стало быть это a, b или их подстроки. Но какие?

fn process<'x>(a &'x str, b: &str) -> &'x str {
...
}

Все, расходимся, это кусок ’a.

Исправление vertexua, :

Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.

в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него

Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager в какие-то асинхронные лямбды.

Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.

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


struct Client<'a> {
  x: &'a FooManager;
}

impl Client {
  fn use_x(self) {
    self.x.call();
  }
}

Client живет время 'a, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client, им владеет кто угодно другой, но живет он как минимум нужное время.

Это накладывает сразу ограничения на весь код, который создает FooManager и Client, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.

let fm = FooManager{};

let client = Client{x: &fm}; // fm живет дольше client.

// Сначала невидимое освобождение client, только потом FooManager.

Лайфтаймы еще помогают в сигнатурах функций

fn process(a &str, b: &str) -> &str {
...
}

Тут не совсем ясно, мы одалживаем две строки, и возвращаем тоже ссылку на какую-то одолженую строку… Еее явно не создали внутри, так как все собственники внутри умерли по выходу из фунции. Стало быть это a, b или их подстроки. Но какие?

fn process<'a>(a &'a str, b: &str) -> &'a str {
...
}

Все, расходимся, это кусок ’a.

Исправление vertexua, :

Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.

в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него

Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager в какие-то асинхронные лямбды.

Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.

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


struct Client<'a> {
  x: &'a FooManager;
}

impl Client {
  fn use_x(self) {
    self.x.call();
  }
}

Client живет время 'a, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client, им владеет кто угодно другой, но живет он как минимум нужное время.

Это накладывает сразу ограничения на весь код, который создает FooManager и Client, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.

let fm = FooManager{};

let client = Client{x: &fm}; // fm живет дольше client.

// Сначала невидимое освобождение client, только потом FooManager.

Исходная версия vertexua, :

Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.

в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него

Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager в какие-то асинхронные лямбды.

Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.

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


struct Client<'a> {
  x: &'a FooManager;
}

impl Client {
  fn use_x(self) {
    self.x.call();
  }
}

Client живет время 'a, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client, им владеет кто угодно другой, но живет он как минимум нужное время.

Это накладывает сразу ограничения на весь код, который создает FooManager и Client, но главная фича тут в том, что это *не забота Client об этом парится". Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.

let fm = FooManager{};

let client = Client{x: &fm}; // fm живет дольше client.

// Сначала невидимое освобождение client, только потом FooManager.