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

Обобщённые функции

Rust поддерживает обобщения, которые позволяют абстрагировать алгоритмы или структуры данных (например, сортировку или двоичное дерево) от типов, которые в них используются или хранятся.

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

fn pick<T>(cond: bool, left: T, right: T) -> T {
    if cond { left } else { right }
}

fn main() {
    println!("picked a number: {:?}", pick(true, 222, 333));
    println!("picked a string: {:?}", pick(false, 'L', 'R'));
}
This slide should take about 5 minutes.
  • Может быть полезно показать мономорфизированные версии pick — либо до разговора об обобщённом pick, чтобы показать, как обобщения уменьшают дублирование кода, либо после разговора об обобщениях, чтобы показать, как работает мономорфизация.

    #![allow(unused)]
    fn main() {
    // Copyright 2023 Google LLC
    // SPDX-License-Identifier: Apache-2.0
    
    fn pick_i32(cond: bool, left: i32, right: i32) -> i32 {
        if cond { left } else { right }
    }
    
    fn pick_char(cond: bool, left: char, right: char) -> char {
        if cond { left } else { right }
    }
    }
  • Rust выводит тип для T на основе типов аргументов и возвращаемого значения.

  • В этом примере для T мы используем только примитивные типы i32 и char, но здесь можно использовать любой тип, в том числе пользовательские:

    // Copyright 2023 Google LLC
    // SPDX-License-Identifier: Apache-2.0
    
    struct Foo {
        val: u8,
    }
    
    pick(false, Foo { val: 7 }, Foo { val: 99 });
  • Это похоже на шаблоны C++, но Rust частично компилирует обобщённую функцию сразу, поэтому функция должна быть корректна для всех типов, удовлетворяющих ограничениям. Например, попробуйте изменить pick, чтобы он возвращал left + right, если cond ложно. Даже если используется только версия pick для целых чисел, Rust всё равно считает код некорректным. C++ позволил бы сделать это.

  • Обобщённый код превращается в необобщённый на основе точек вызова. Это абстракция с нулевой стоимостью: вы получаете ровно тот же результат, как если бы вручную написали структуры данных без абстракции.