Нещодавно виступ Дейва Германа в Русті сказав, що вони запозичили це майно у C ++. Я не міг знайти нічого навколо теми. Хтось може пояснити, що означає мономорфізація?
Нещодавно виступ Дейва Германа в Русті сказав, що вони запозичили це майно у C ++. Я не міг знайти нічого навколо теми. Хтось може пояснити, що означає мономорфізація?
Відповіді:
Мономорфізація означає генерацію спеціалізованих версій загальних функцій. Якщо я напишу функцію, яка витягує перший елемент будь-якої пари:
fn first<A, B>(pair: (A, B)) -> A {
let (a, b) = pair;
return a;
}
а потім двічі викликаю цю функцію:
first((1, 2));
first(("a", "b"));
Компілятор згенерує дві версії first()
, одна спеціалізована для пар цілих чисел і одна спеціалізована для пар рядків.
Назва походить від терміну мови програмування "поліморфізм" - означає одну функцію, яка може мати справу з багатьма типами даних. Мономорфізація - це перетворення з поліморфного в мономорфний код.
Не впевнений, що хтось все ще дивиться на це, але в документації Rust насправді згадується, як він не дозволяє скоротити витрати за допомогою цього процесу. Від продуктивності коду з використанням дженериків :
Можливо, вам цікаво, чи існує вартість виконання, коли ви використовуєте загальні параметри типу. Хороша новина полягає в тому, що Rust впроваджує загальні засоби таким чином, що ваш код не працює повільніше, використовуючи загальні типи, ніж це було б для конкретних типів.
Руст досягає цього, виконуючи мономорфізацію коду, який використовує загальні засоби під час компіляції. Мономорфізація - це процес перетворення загального коду на конкретний код шляхом заповнення конкретних типів, які використовуються при компіляції.
У цьому процесі компілятор робить протилежні кроки, які ми використовували для створення загальної функції в лістингу 10-5: компілятор переглядає всі місця, де викликається загальний код, і генерує код для конкретних типів, з якими викликається загальний код .
Давайте подивимось, як це працює, на прикладі, який використовує перелік Option стандартної бібліотеки:
let integer = Some(5); let float = Some(5.0);
Коли Руст компілює цей код, він виконує мономорфізацію. Під час цього процесу компілятор читає значення, які використовувались у примірниках Option, і визначає два типи Option: один - i32, а другий - f64. Як такий, він розширює загальне визначення Option на Option_i32 та Option_f64, тим самим замінюючи загальне визначення конкретними.
Мономорфізована версія коду виглядає наступним чином. Загальний параметр замінюється конкретними визначеннями, створеними компілятором:
// Filename: src/main.rs enum Option_i32 { Some(i32), None, } enum Option_f64 { Some(f64), None, } fn main() { let integer = Option_i32::Some(5); let float = Option_f64::Some(5.0); }
Оскільки Rust компілює загальний код у код, який вказує тип у кожному екземплярі, ми не платимо за час використання загальних кодів. Коли код працює, він працює так само, як і в тому випадку, якби ми продублювали кожне визначення вручну. Процес мономорфізації робить дженерики Rust надзвичайно ефективними під час виконання.
Не впевнений у цьому; Ви могли б зробити посилання на розмову? Можливо, це було ненавмисне зауваження.
Герман міг би ввести термін для чогось на зразок спеціалізації шаблону, який генерує типи / об'єкти, які взаємопов'язані (не поліморфні чи "мономорфні") із шаблону, який є поліморфною структурою.
У Книзі іржі є гарне пояснення мономорфізації
Мономорфізація - це процес перетворення загального коду на конкретний код шляхом заповнення конкретних типів, які використовуються при компіляції.
З прикладу книги, якщо ви визначили змінні за допомогою Some
:
let integer = Some(5); let float = Some(5.0);
Коли Руст компілює цей код, він виконує мономорфізацію. Під час цього процесу компілятор читає значення, які використовувались у
Option<T>
екземплярах, і визначає два типиOption<T>
: один є,i32
а інший -f64
. Як такий, він розширює загальне визначенняOption<T>
вOption_i32
іOption_f64
, таким чином , замінивши загальне визначення з конкретними з них.Мономорфізована версія коду виглядає наступним чином. Загальний
Option<T>
змінено замінено конкретними визначеннями, створеними компілятором:Ім'я файлу: src / main.rs
enum Option_i32 { Some(i32), None, } enum Option_f64 { Some(f64), None, } fn main() { let integer = Option_i32::Some(5); let float = Option_f64::Some(5.0); }