Rust-ohjelmoinnin perusteet · Oppitunti

Geneeriset funktiot

Parametrisoikaa toiminta tyypin mukaan.

Oppitunti 1/413 vaihetta

Geneeriset funktiot on ilmainen Rust-ohjelmoinnin perusteet-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Rust-ohjelmoinnin perusteet-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Rust-ohjelmoinnin perusteet-kurssilla on yhteensä 4 oppituntia.

Miksi geneerisiä funktioita käytetään

Geneeristen funktioiden avulla voitte kirjoittaa yhden funktion, joka toimii monilla tyypeillä, sen sijaan että kopioisitte koodin jokaista tyyppiä varten. Rust korvaa paikkamerkkityypin käännöksen aikana.

Ajatelkaa, että kirjoittaisitte yhden largest-funktion kokonaisluvuille ja toisen merkeille. Geneerisyys yhdistää nämä yhdeksi määrittelyksi ilman ajonaikaista kustannusta.

Tyyppiparametrit

Geneerinen funktio ilmoittaa tyyppiparametrin kulmasulkeissa nimen jälkeen. Nimi T on käytäntö, mutta mikä tahansa CamelCase-tunniste käy.

Parametri voidaan sen jälkeen sijoittaa argumentteihin ja paluutyyppiin, jolloin se edustaa mitä tahansa kutsujan käyttämää konkreettista tyyppiä.

fn first<T>(pair: (T, T)) -> T {
    pair.0
}

Yksinkertainen identiteettifunktio

Tämä ohjelma määrittelee geneerisen echo-funktion, joka palauttaa argumenttinsa muuttamattomana. Sitä kutsutaan kerran kokonaisluvulla ja kerran merkkijonoviipaleella.

Kääntäjä tuottaa erillisen konkreettisen version jokaiselle tosiasiassa käytetylle tyypille.

fn echo<T>(value: T) -> T {
    value
}

fn main() {
    println!("{}", echo(42));
    println!("{}", echo("hi"));
}

Monomorfisointi

Rust käyttää monomorfisointia: käännöksen aikana se tuottaa funktiosta erikoistetun kopion jokaiselle käytetylle konkreettiselle tyypille. Boksauksia tai virtuaalista metodikutsua ei tarvita.

Tuloksena on geneeristä koodia, joka suoritetaan yhtä nopeasti kuin käsin kirjoitettu tyyppikohtainen koodi.

Geneeriset tyypit tarvitsevat rajoitteita

Geneerisessä funktiossa voitte käyttää vain toimintoja, joita kaikki mahdolliset tyypit tukevat. Pelkkää T-tyyppiä ei voi yhteenlaskaa, vertailla tai tulostaa.

Tämä koodi ei käänny, koska T ei välttämättä toteuta vertailua. Korjaamme tilanteen seuraavaksi trait-rajoitteella.

fn larger<T>(a: T, b: T) -> T {
    if a > b { a } else { b }
}

Trait-rajoitteen lisääminen

Arvojen vertailemiseksi rajoitamme T-tyypin PartialOrd-traitilla. Rajoite lupaa, että tyyppi tukee >-operaattoria.

Lisäämme myös Copy-traitin, jotta arvot voidaan palauttaa ilman siirtämiseen liittyviä ongelmia esimerkiksi kokonaislukujen kaltaisilla yksinkertaisilla tyypeillä.

fn larger<T: PartialOrd + Copy>(a: T, b: T) -> T {
    if a > b { a } else { b }
}

Rajoitetun funktion kutsuminen

Nyt funktio toimii kaikilla tyypeillä, jotka toteuttavat molemmat traitit. Sekä kokonaisluvut että liukuluvut täyttävät ehdon PartialOrd + Copy.

Sama lähdekoodi, joka monomorfisoidaan kahdeksi versioksi, tulostaa tulokset kummallekin kutsulle.

fn larger<T: PartialOrd + Copy>(a: T, b: T) -> T {
    if a > b { a } else { b }
}

fn main() {
    println!("{}", larger(3, 9));
    println!("{}", larger(2.5, 1.0));
}

Useita tyyppiparametreja

Funktio voi ilmoittaa useita tyyppiparametreja. Kukin niistä on itsenäinen, joten kahdella argumentilla voi olla eri tyypit.

Tässä pair hyväksyy minkä tahansa T- ja U-tyypin ja palauttaa ne duplena.

fn pair<T, U>(a: T, b: U) -> (T, U) {
    (a, b)
}

Geneeristen arvojen tulostaminen

Geneerisen arvon tulostamiseksi muodolla {} tyypin on toteutettava Display. Lisäämme tämän rajoitteen, jotta mikä tahansa tulostettava tyyppi voidaan välittää.

Funktio nimeää arvon ja palauttaa sen, mikä havainnollistaa pelkästään muotoilua varten käytettävää rajoitetta.

use std::fmt::Display;

fn announce<T: Display>(label: &str, value: T) {
    println!("{}: {}", label, value);
}

fn main() {
    announce("count", 7);
    announce("name", "Ada");
}

Turbofish-syntaksi

Joskus kääntäjä ei pysty päättelemään T-tyyppiä pelkkien argumenttien perusteella. Turbofish-syntaksilla ::<Type> voitte määrittää tyypin suoraan kutsukohdassa.

Sitä käytetään tavallisimmin metodien, kuten parse- ja collect-metodien, kanssa, kun paluutyyppi on epäselvä.

fn main() {
    let n = "42".parse::<i32>().unwrap();
    println!("{}", n + 1);
}

Geneerisyys viitteiden kanssa

Geneeriset parametrit toimivat myös viitteiden kanssa. Viitteeseen perustuva rajoitus välttää Copy-traitin vaatimusen, kun arvoja tarvitsee vain lukea.

Tämä longest_str-tyylinen apufunktio lainaa kaksi viipaletta ja palauttaa toisen ottamatta omistajuutta.

fn pick<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> &'a T {
    if a > b { a } else { b }
}

Pikatarkistus

Testatkaa ymmärrystänne Rustin geneerisistä funktioista.

Kertaus

Geneeriset funktiot käyttävät kulmasulkeissa olevia tyyppiparametreja toimiakseen monilla tyypeillä ilman ajonaikaista kustannusta monomorfisoinnin ansiosta.

Geneeriseen tyyppiin kohdistuvat toiminnot edellyttävät trait-rajoitteita, kuten PartialOrd, Copy tai Display. Käyttäkää turbofish-syntaksia, kun tyyppiä ei voida päätellä.

Aloita maksutta

Opi Rust tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
39
Oppitunnit
144

Usein kysytyt kysymykset

Onko oppitunti ”Geneeriset funktiot” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Rust-ohjelmoinnin perusteet-oppimispolun 3 oppituntia, myös oppitunnin “Geneeriset funktiot”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Rust-ohjelmoinnin perusteet-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Geneeriset funktiot”?

Parametrisoikaa toiminta tyypin mukaan. Harjoittelet Rust-ohjelmoinnin perusteet-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Rust-ohjelmoinnin perusteet-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Rust-ohjelmoinnin perusteet-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.

Kuinka kauan ”Geneeriset funktiot”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Rust-ohjelmoinnin perusteet-oppitunnilla?

Kyllä. Jokainen Rust-ohjelmoinnin perusteet-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Geneeriset funktiot
  2. Geneeriset structit ja enumit
  3. Trait-rajoitteet
  4. where-lausekkeet ja useat rajoitteet
← Takaisin: Rust-ohjelmoinnin perusteet