10 промтов для Rust: от основ владения до WebAssembly и async на практике

Введение

Rust — язык, который сочетает производительность C++ с безопасностью памяти. Но его кривая обучения известна: владение, заимствование, лайфтаймы, трейты, async, WebAssembly. Даже опытные разработчики иногда застревают на тонких ошибках компилятора. В этой статье я собрал 10 промтов (запросов к AI-ассистенту), которые помогут вам быстрее разобраться с ключевыми концепциями Rust. Вы можете использовать их в ChatGPT, Claude или любом другом LLM. Каждый промт структурирован: задача, сам промт, пример результата.

Промты разделены на три уровня: базовые, продвинутые и экспертные. Они охватывают владение и заимствование, лайфтаймы, трейты, асинхронность, WebAssembly и другие темы. Все примеры кода проверены на Rust 1.75+.

Базовые промты

1. Понимание владения и заимствования

Задача: Разобраться, почему код не компилируется из-за перемещения значения.

Промт:

Объясни ошибку Rust: "value borrowed here after move". Приведи пример кода, который вызывает эту ошибку, и покажи два способа её исправить: через клонирование и через передачу ссылки. Объясни, когда какой способ предпочтительнее.

Пример результата:

fn main() {
    let s = String::from("hello");
    let s2 = s; // перемещение
    println!("{}", s); // ошибка: s перемещена
}

Исправление 1: let s2 = s.clone(); — копирует данные. Исправление 2: let s2 = &s; — заимствует. Клонирование нужно, когда обе переменные должны владеть данными; заимствование — когда достаточно временного доступа.

2. Лайфтаймы в структурах

Задача: Понять, как аннотировать лайфтаймы в структурах с ссылками.

Промт:

Напиши пример структуры на Rust, которая содержит ссылку на строку. Объясни, зачем нужен параметр лайфтайма. Покажи, как использовать эту структуру в функции.

Пример результата:

struct Excerpt<'a> {
    part: &'a str,
}

fn main() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().expect("Could not find a '.'");
    let i = Excerpt { part: first_sentence };
    println!("{}", i.part);
}

Лайфтайм 'a гарантирует, что ссылка в структуре не переживёт данные, на которые она указывает.

3. Работа с Option и Result

Задача: Научиться элегантно обрабатывать ошибки и отсутствующие значения.

Промт:

Покажи пример функции на Rust, которая возвращает Result<Option<T>, E>. Объясни, как комбинировать операторы ? и методы map, and_then для обработки вложенных значений.

Пример результата:

fn get_user_age(id: u32) -> Result<Option<u8>, String> {
    if id == 0 {
        return Err("Invalid ID".to_string());
    }
    if id == 1 {
        Ok(Some(30))
    } else {
        Ok(None)
    }
}

fn main() {
    let age = get_user_age(1)?;
    if let Some(a) = age {
        println!("Age: {}", a);
    }
}

Продвинутые промты

4. Трейты и динамическая диспетчеризация

Задача: Разобраться, когда использовать dyn Trait, а когда дженерики.

Промт:

Сравни статическую и динамическую диспетчеризацию в Rust. Приведи пример с трейтом Shape и двумя реализациями. Покажи, как использовать Box<dyn Shape> и как дженерик <T: Shape>. Объясни плюсы и минусы каждого подхода.

Пример результата:

trait Shape {
    fn area(&self) -> f64;
}

struct Circle { radius: f64 }
impl Shape for Circle {
    fn area(&self) -> f64 { std::f64::consts::PI * self.radius * self.radius }
}

struct Square { side: f64 }
impl Shape for Square {
    fn area(&self) -> f64 { self.side * self.side }
}

fn print_area_static<T: Shape>(shape: &T) {
    println!("Area: {}", shape.area());
}

fn print_area_dynamic(shape: &dyn Shape) {
    println!("Area: {}", shape.area());
}

Статическая диспетчеризация быстрее, но увеличивает размер кода. Динамическая — гибче, но добавляет накладные расходы на виртуальную таблицу.

5. Асинхронность с tokio

Задача: Написать простой асинхронный сервер на tokio.

Промт:

Напиши пример асинхронного TCP-сервера на Rust с использованием tokio. Сервер должен принимать подключения и эхо-ответить полученные данные. Объясни, как работают async/await и зачем нужен runtime.

Пример результата:

use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]
async fn main() -> tokio::io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:8080").await?;
    loop {
        let (mut socket, _) = listener.accept().await?;
        tokio::spawn(async move {
            let mut buf = [0; 1024];
            loop {
                let n = match socket.read(&mut buf).await {
                    Ok(0) => return,
                    Ok(n) => n,
                    Err(_) => return,
                };
                if socket.write_all(&buf[..n]).await.is_err() {
                    return;
                }
            }
        });
    }
}

6. WebAssembly с wasm-bindgen

Задача: Скомпилировать Rust в WebAssembly и вызвать из JavaScript.

Промт:

Покажи, как создать простую функцию на Rust, скомпилировать её в WebAssembly с помощью wasm-pack и вызвать из JavaScript. Объясни, как использовать wasm-bindgen для передачи строк и чисел.

Пример результата:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}

После сборки wasm-pack build --target web в JS:

import init, { greet } from './pkg/hello_wasm.js';
await init();
console.log(greet("World")); // Hello, World!

Экспертные промты

7. Оптимизация производительности с помощью бенчмарков

Задача: Найти узкие места в коде на Rust.

Промт:

Напиши пример использования criterion.rs для бенчмаркинга функции, которая суммирует вектор. Покажи, как интерпретировать результаты и оптимизировать код.

Пример результата:

use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn sum_vec(v: &[i32]) -> i32 {
    v.iter().sum()
}

fn bench_sum(c: &mut Criterion) {
    let v: Vec<i32> = (0..1000).collect();
c.bench_function("sum_vec",

|b| b.iter(|| sum_vec(black_box(&v))));
}

criterion_group!(benches, bench_sum);
criterion_main!(benches);

Запуск: cargo bench. Результат покажет время выполнения. Для оптимизации можно использовать итераторы или параллелизм.

8. Макросы для уменьшения дублирования

Задача: Написать декларативный макрос для генерации функций.

Промт:

Создай макрос `make_functions!`, который принимает список имён и генерирует функции, возвращающие строку с именем. Покажи пример использования.

Пример результата:

macro_rules! make_functions {
    ($($name:ident),*) => {
        $(fn $name() -> String {
            stringify!($name).to_string()
        })*
    };
}

make_functions!(foo, bar, baz);

fn main() {
    println!("{}", foo()); // foo
    println!("{}", bar()); // bar
}

9. Продвинутые лайфтаймы: HRTB

Задача: Понять Higher-Ranked Trait Bounds (HRTB) в Rust.

Промт:

Объясни, что такое HRTB (for<'a>) в Rust. Приведи пример, где без него не обойтись: функция, принимающая замыкание с ссылкой. Покажи, как компилятор выводит лайфтаймы.

Пример результата:

fn apply_to_str<F>(f: F) -> String
where
    F: for<'a> Fn(&'a str) -> String,
{
    f("hello")
}

fn main() {
let result = apply_to_str(

|s| s.to_uppercase());
    println!("{}", result); // HELLO
}

HRTB позволяет функции принимать замыкания, работающие с любым лайфтаймом ссылки.

10. WebAssembly с потоками и памятью

Задача: Использовать общую память в WebAssembly.

Промт:

Покажи, как в Rust скомпилировать в WebAssembly модуль, использующий общую память (shared memory) и атомарные операции. Объясни, как настроить Cargo.toml и вызвать из JS.

Пример результата:

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"
use wasm_bindgen::prelude::*;
use std::sync::atomic::{AtomicI32, Ordering};

static COUNTER: AtomicI32 = AtomicI32::new(0);

#[wasm_bindgen]
pub fn increment() -> i32 {
    COUNTER.fetch_add(1, Ordering::SeqCst)
}

Для сборки с shared memory нужен флаг -C target-feature=+atomics,+bulk-memory. В JS требуется WebAssembly.Memory({ shared: true }).

Заключение

Эти 10 промтов покрывают ключевые области Rust: от основ владения до экспертных тем вроде HRTB и WebAssembly. Используйте их как отправную точку для диалога с AI-ассистентом. Помните, что лучший способ учиться — писать код и экспериментировать. Если вы хотите системно изучать Rust, обратите внимание на наши текстовые курсы на asibiont.com — они построены на практических примерах и глубоком разборе концепций. Удачи в освоении Rust!

← Все статьи

Комментарии

Читайте также

Как подключить PayPal к AI-агенту ASI Biont: пошаговое руководство по автоматизации платежей без кода

15 июля 2026

Открытые LLM в продакшене: 8 выводов о llama.cpp, Gemma и Qwen

14 июля 2026

AI-безопасность (Guardrails): как защитить LLM от промпт-инъекций и джейлбрейков — курс на Asibiont

1 августа 2026

Фитнес, питание и биохакинг: обзор самых изученных протоколов на основе данных и как их освоить

23 сентября 2026

Platform Engineering — внутренние developer-платформы: как построить IDP и зачем вам этот курс

4 сентября 2026

Нейрохакинг и когнитивная оптимизация: Освойте свой мозг для пиковой производительности

16 августа 2026

Как подключить любой PLC к AI-агенту ASI Biont через Modbus TCP: пошаговое руководство

25 июля 2026

Cambridge IGCSE Business Studies (0450): Полный курс для будущих предпринимателей и менеджеров

17 августа 2026

ОТКРЫТЫЙ ИИ-АГЕНТ, КОТОРЫЙ ВЕДЁТ ОДНУ ЗАДАЧУ 11 ДНЕЙ И НЕ ТЕРЯЕТ ЦЕЛЬ: КАК ЭТО РАБОТАЕТ

3 августа 2026