D (ohjelmointikieli)

Ominaisuudet

D:n suunnittelussa on otettu huomioon C++:n käytössä vuosien aikana kertyneitä kokemuksia. D käyttää monia C++:n konsepteja ja laajentaa toiminnallisuutta toteuttamalla kielen tasolla tuottavuutta lisääviä ominaisuuksia, joita ovat esimerkiksi sopimuspohjainen ohjelmointi, yksikkötestaus, aidot ohjelmamoduulit, roskienkeruu, ensimmäisen luokan oliot, kehittyneet taulukko- ja assosiatiivinen taulukko-tietotyypit, sisäluokat ja -funktiot, sulkeumat ja uudelleen suunniteltu geneerinen ohjelmointi. D mahdollistaa C++:n lailla matalan tason ohjelmoinnin, jossa apuna voidaan käyttää kääntäjän assembleria. C++:n moniperintä on korvattu tavallisella yksinkertaisella perinnällä, rajapinnoilla ja mixineillä. D:n esittelyt, lauseet ja lausekkeet muistuttavat läheisesti C++:n vastaavia.

Yhteensopivuus muiden järjestelmien kanssa

D tukee täydellisesti C-kielen ABI-rajapintaa (Application Binary Interface) sekä C:n tietotyyppejä ja mahdollistaa näin suoran pääsyn C-kieliseen ohjelmakoodiin ja kirjastoihin. C:n standardikirjasto on osa standardia D-kieltä. Koska D ei vielä ole standardoitu, tarkoitetaan tällä Digital Marsin referenssi-implementaatiota ja -spesifikaatiota.
C++:n ABI ei ole tuettu, mutta D-kielestä voidaan kutsua C-kielen ABI:n kautta C++-koodia, joka on kääritty C-kielisiin funktioihin. D kuitenkin tukee täysin C++-kielistä COM (Component Object Model) koodia.

Toteutukset

Nykyiset D:n toteutukset kääntävät ohjelmat suoraan natiivikoodiksi. Tällä hetkellä merkittävimmät kääntäjät D:lle ovat Digital Marsin DMD sekä vapaa GDC.
DMD:n etuosa (selaaja, jäsennin) on julkaistu GNU GPL:n ja Artistic License:n alla. Toteutuksen tekijänoikeudet omistaa pääosin Digital Mars, muilta osin koodi on joko public domainia tai muun yhteensopivan vapaan lisenssin alla. Kääntäjä perustuu viralliseen D-spesifikaatioon, mutta on suljettua lähdekoodia ja tukee ainoastaan Windows- ja Linux/x86-alustoja.
Toinen merkittävä D-kääntäjä, GDC, yhdistää DMD:n etuosan GCC:tä käyttävään takaosaan. GDC toimii teoriassa kaikilla alustoilla, joilla GCC:kin, ja on lisäksi julkaistu vapaan GNU GPL -lisenssin alla. GDC on käytännön syistä ajoittain spesifikaation osalta jäljessä virallista kääntäjää. Linux-jakeluista ainakin Debian, Gentoo ja Ubuntu tarjoavat kääntäjää paketinhallintansa kautta. Kääntäjä on mahdollista asentaa myös dsss-järjestelmän kautta. DSSS on esimerkiksi CPAN ja RubyGems -järjestelmiä vastaava asennustyökalu D-kielelle.
D on yhä aktiivisen kehitystyön alla ja sen kääntäjistä julkaistaan säännöllisesti uusia versioita. Kääntäjän 1.0-haaraan ilmestyy lähinnä bugikorjauksia, mutta 2.0-haaraan myös epävakaita uusia toimintoja. Ehkä merkittävin muutos 2.0-versiossa on C++-kielen const-järjestelmän vastine. D 2.0 sisältänee ilmestyessään myös monia muita uusia ominaisuuksia, kuten aidot sulkeumat, paremman muistimallin monisäikeiselle ohjelmoinnille, suurehkon päivityksen standardikirjastoon ja monia pienempiä korjauksia.

Hei maailma

Tämä esimerkki kirjoittaa ruudulle sanat "Hei maailma!" ja sen jälkeen komentorivin argumentit. Jokaisen D-ohjelman suorittaminen alkaa main funktiosta, ja args on merkkijonojen taulukko, jossa komentorivin argumentit ovat. Argumentit ovat valinnaisia. Merkkijonoa kuvataan D:ssä tyypillä string. D 1.x:ssä string on alias merkkijonojen taulukolle(char[]), mutta 2.x estää merkkijonon muokkaamisen. Useiden merkkijonojen taulukko on vastaavasti string[].
import std.stdio;       // tuo writefln()int main(string[] args){
    writefln("Hei maailma!");
    foreach(indeksi, arvo; args)
        writefln("args[%d] = '%s'", indeksi, arvo);
    return 0;}
foreach-lauseella voidaan käydä läpi mikä tahansa kokoelma. Vakiotietotyypit tarjoavat oletustoiminnallisuuden, mutta iterointi voidaan tarvittaessa erikoistaa määritellyissä luokissa. Lause päättelee indeksin ja arvon tyypit automaattisesti, mutta ne voidaan myös ilmoittaa.

Hajautustaulukot

Esimerkki havainnollistaa hajautustaulujen käyttöä monimutkaisen tietorakenteen rakentamisessa.
import std.stdio;       // tuo writefln()int main(string[] args){
    // Määritellään hajautustaulu, jossa arvoina on taulukoita merkkijonoista ja
    // avaimena merkkijono
    string[] [string] säiliö;

    // Lisätään säiliöön henkilöitä ja heille esineitä
    säiliö["Tuomikki"] ~= "puukko";
    säiliö["Airikka"] ~= "löylykauha";
    säiliö["Tuomikki"] ~= "puhelin";

    // Käydään läpi säiliön henkilöt
    foreach (string henkilö, string[] esineet; säiliö)
        kerro_montako_esinettä(henkilö, esineet);
    return 0; // ohjelma onnistui}void kerro_montako_esinettä(string henkilö, string[] esineet){
    writefln(henkilö, " kantaa ", esineet.length, " esinettä.");}

Metaohjelmointi

Esimerkki näyttää, miten D mahdollistaa koodin suorittamisen käännösaikana.
// Malli, joka esittelee static if -lauseen käyttöä.template Kertoma(ulong n) {
    static if( n <= 1 )
        const Kertoma = 1;
    else
        const Kertoma = n * Kertoma!(n-1);}// Vertailun vuoksi kertomafunktioulong kertoma(ulong n) {
    if( n <= 1 )
        return 1;
    else
        return n * kertoma(n-1);}// mallin instantiointi, paluuarvon evaluointi,// tyypin päättely ja vakion asetusconst kert_7 = Kertoma!(7);// käännösaikainen funktion suoritus,// tyypin päättely ja vakion asetusconst kert_9 = kertoma(9);// arvoja voidaan tulostaa näytölle käännösaikana ja muotoilla// esimerkiksi printf-tyylisellä Format-mallillaimport std.metastrings;pragma(msg, Format!("7! = %s", kert_7));pragma(msg, Format!("9! = %s", kert_9));// käännös voidaan keskeyttää esimerkiksi virhetilanteissastatic assert(kert_7 != 5040, "Laskualgoritmi on virheellinen");