Przejdź do zawartości

D (język programowania): Różnice pomiędzy wersjami

Z Wikipedii, wolnej encyklopedii
[wersja przejrzana][wersja przejrzana]
Usunięta treść Dodana treść
Addbot (dyskusja | edycje)
m Bot: Przenoszę 28 linków interwiki do Wikidata, znajdziesz je teraz w zasobie d:q319268
Vebace (dyskusja | edycje)
drobne merytoryczne, źródła/przypisy
Linia 5: Linia 5:
|typowanie = [[statyczna typizacja|statyczne]] ([[silna typizacja|silne]])
|typowanie = [[statyczna typizacja|statyczne]] ([[silna typizacja|silne]])
|implementacje = Digital Mars D, [[Low Level Virtual Machine|LLVM]], [[GNU Compiler Collection|GCC]]
|implementacje = Digital Mars D, [[Low Level Virtual Machine|LLVM]], [[GNU Compiler Collection|GCC]]
|wersja = 1.076/2.062<ref>{{Cytuj stronę | url = http://www.digitalmars.com/d/1.0/changelog.html | tytuł = Changelog | data dostępu = 31 grudnia 2012 | praca = D Programming Language 1.0 | opublikowany = Digital Mars | język = en }}</ref><ref>{{Cytuj stronę | url = http://dlang.org/changelog.html | tytuł = Changelog | data dostępu = 31 grudnia 2012 | praca = D Programming Language 2.0 | opublikowany = Digital Mars | język = en }}</ref></br>{{Data wydania|2013|01|01}}
|wersja = 1.072 - {{Data wydania|2011|12|5}}<br/> 2.060 - {{Data wydania|2012|08|02}}
|twórca = [[Walter Bright]]
|twórca = [[Walter Bright]]
|platforma = [[wieloplatformowość|wieloplatformowy]]
|platforma = [[wieloplatformowość|wieloplatformowy]]

Wersja z 17:16, 5 kwi 2013

D
logo
Pojawienie się

2007

Paradygmat

wieloparadygmatowy

Typowanie

statyczne (silne)

Implementacje

Digital Mars D, LLVM, GCC

Aktualna wersja stabilna

1.076/2.062[1][2]
1 stycznia 2013; ponad 11 lat temu

Twórca

Walter Bright

Platforma sprzętowa

wieloplatformowy

Platforma systemowa

wieloplatformowy

Strona internetowa

Język Dwieloparadygmatowy język programowania umożliwiający programowanie obiektowe, imperatywne oraz metaprogramowanie. Został opracowany przez Waltera Brighta, twórcę pierwszego natywnego kompilatora C++, Zortech C++. D powstał jako obiektowy następca języka C, jednak w przeciwieństwie do C++ zachowuje ze swoim poprzednikiem jedynie binarną kompatybilność. D posiada wiele cech obecnych w C++, a jego składnia oraz możliwości są wzorowane na Javie, C# oraz Eiffel[potrzebny przypis]. Pierwsza stabilna wersja języka ukazała się 2 stycznia 2007 roku[3]. 17 czerwca 2007 roku opublikowano po raz pierwszy eksperymentalną wersję 2.0[4].

Możliwości

Język D jest projektowany bardziej z praktycznej, niż z teoretycznej perspektywy. Jego składnia oraz możliwości zostały opracowane na podstawie praktycznych wniosków z użytkowania oraz implementowania C++. Zrezygnowano z wstecznej kompatybilności kodu źródłowego na rzecz przejrzystej, bezkontekstowej gramatyki ułatwiającej tworzenie kompilatorów, a także z niektórych możliwości dostępnych w C++ takich, jak wielokrotne dziedziczenie na rzecz interfejsów i domieszkowania. W zamian wprowadzono wiele nowoczesnych rozwiązań: programowanie kontraktowe, prawdziwe moduły, wbudowane automatyczne zarządzanie pamięcią (przez garbage collector), testy jednostkowe, tablice asocjacyjne, tablice dynamiczne, domknięcia, funkcje anonimowe, funkcje zagnieżdżone, klasy wewnętrzne, leniwe wartościowanie oraz zintegrowany z kompilatorem system dokumentacji ddoc. Oprócz tego całkowicie przeprojektowano mechanizm szablonów. Utrzymana została możliwość tworzenia niskopoziomowego kodu oraz umieszczania wstawek asemblerowych.

Paradygmaty programowania

D wspiera trzy główne paradygmaty programowania: imperatywne, obiektowe oraz metaprogramowanie.

Programowanie imperatywne

Programowanie imperatywne wygląda niemal identycznie, jak w C. Dostępne są klasyczne pętle, instrukcje warunkowe, funkcje, zmienne lokalne i globalne oraz wyrażenia, które działają identycznie, jak w pierwowzorze, a programy mają bezpośredni dostęp do biblioteki standardowej C. Ponadto wprowadzone zostały dwa rozszerzenia w postaci instrukcji foreach do iterowania po kolekcjach oraz funkcji zagnieżdżonych, które mają dostęp do zmiennych lokalnych funkcji nadrzędnej.

Programowanie obiektowe

Klasy w D tworzą pojedynczą hierarchię wywodzącą się z klasy Object. Język nie wspiera wielokrotnego dziedziczenia, proponując w zamian interfejsy w stylu Javy oraz domieszki, które umożliwiają przeniesienie współdzielonej funkcjonalności poza hierarchię klas.

D zmienia również sposób obsługi metod wirtualnych. Domyślnie każda metoda, która nie jest statyczna, prywatna oraz szablonowa, staje się metodą wirtualną. Kompilator analizuje hierarchię klas, określając które metody wirtualne można wywoływać statycznie oraz w jakim kontekście, co pozwala na lepszą optymalizację kodu wynikowego oraz uniknięcie wielu błędów programistycznych.

Metaprogramowanie

Metaprogramowanie jest wspierane przez kombinację szablonów, wykonywania funkcji w trakcie kompilacji, krotek oraz domieszkowania tekstu. Poniższe przykłady demonstrują niektóre możliwości metaprogramowania w D.

W przeciwieństwie do C++, szablony w D bardziej przypominają funkcje. Poniższy przykład pokazuje wykorzystanie statycznego ifa, instrukcji wykonywanej w trakcie kompilacji, do obliczania wartości silni:

template Factorial(ulong n)
{
    static if(n <= 1)
        const Factorial = 1;
    else
        const Factorial = n * Factorial!(n - 1);
}

Poniżej pokazana jest natomiast klasyczna funkcja, która bardzo przypomina wersję z szablonem:

ulong factorial(ulong n)
{
    if(n <= 1)
        return 1;
    else
        return n * factorial(n - 1);
}

Poniżej pokazane jest wykorzystanie szablonu i funkcji do obliczenia wartości silni w trakcie kompilacji. W języku D nie ma konieczności deklarowania typów stałych, ponieważ mogą one zostać wyliczone z prawej strony wyrażenia.

const fact_7 = Factorial!(7);

Zwykłe funkcje mogą być obliczone w trakcie kompilacji, gdy są użyte w stałych wyrażeniach spełniających określone kryteria.

const fact_9 = factorial(9);

Szablon std.metastrings.Format udostępnia formatowanie tekstu w stylu printf, którego wynik jest wyświetlany podczas kompilacji przez dyrektywę msg.

import std.metastrings;
pragma(msg, Format!("7! = %s", fact_7));
pragma(msg, Format!("9! = %s", fact_9));

Domieszkowanie tekstu w połączeniu z funkcjami wykonywanymi w trakcie kompilacji pozwala na dynamiczne generowanie kodu D podczas kompilowania programu. Może to być wykorzystane do parsowania języków dziedzinowych do kodu D, który następnie jest włączany jako część powstającego programu D.

import FooToD; // hipotetyczny moduł z funkcją tłumaczącą język Foo na D

void main()
{
    mixin(fooToD(import("example.foo")));
}

Zarządzanie pamięcią

Choć D jest kompilowany do kodu maszynowego, zarządzanie pamięcią domyślnie odbywa się za pośrednictwem odśmiecacza pamięci, identycznie jak w językach interpretowanych. Część obiektów może być usuwana natychmiast po znalezieniu się poza zasięgiem. Pomimo tego, programista ma pełną kontrolę nad całym procesem. Dozwolone jest ręczne alokowanie i zwalnianie pamięci poprzez przeciążone operatory new oraz delete lub poprzez zwyczajne wywołanie funkcji malloc() oraz free() z biblioteki standardowej C. Możliwe jest zmienianie zakresów pamięci obserwowanych przez odśmiecacz, wstrzymywanie i wznawianie jego pracy, a także wymuszanie wykonania ogólnego lub pełnego czyszczenia. Dokumentacja podaje przykłady implementacji innych technik zarządzania pamięcią dla sytuacji, w których odśmiecanie nie jest optymalnym rozwiązaniem.

Łączenie z innymi językami

Język D jest binarnie kompatybilny z C, co pozwala łączyć napisane w nim programy ze wszystkimi bibliotekami C, w tym również z biblioteką standardową tego języka, która jest także częścią biblioteki standardowej D.

Łączenie z kodem C++ nie jest obsługiwane przez wersję 1.0. Eksperymentalna częściowa obsługa pojawiła się w wersji 2.0.

D 2.0

W czerwcu 2007 roku ukazał się D 2.0, nowa eksperymentalna gałąź języka, która koncentruje się na jego dalszej rozbudowie. Niektóre z nowych wprowadzanych przez nią cech to:

  • Częściowa obsługa interfejsu binarnego C++.
  • Iteracja foreach po wybranym wycinku kolekcji.
  • Obsługa prawdziwych domknięć. W wersji 1.0 domknięcia nie mogą być bezpiecznie zwracane przez funkcje, gdyż skutkuje to utratą dostępu do danych zaalokowanych na stosie.
  • Obsługa funkcji czystych, które nie mają efektów ubocznych: mogą odwoływać się jedynie do niezmiennych danych oraz wywoływać inne funkcje czyste. W połączeniu z prawdziwymi domknięciami daje to pełną obsługę programowania funkcyjnego.
  • Funkcje nothrow.
  • Operacje wektorowe, np. c[] = b[] + a[]; (sumowanie odpowiadających sobie elementów z dwóch tablic) lub b[] *= 3; (pomnożenie każdego elementu tablicy przez 3).
  • Ulepszenia w bibliotece standardowej Phobos.

Implementacje

Obecne implementacje języka D generują kod maszynowy, aby zapewnić maksymalną wydajność.

Chociaż D cały czas się rozwija, do wersji 1.0 nie są już wprowadzane żadne zmiany, a cały wysiłek koncentruje się na usuwaniu wykrytych błędów. Oficjalny kompilator Waltera Brighta definiuje jednocześnie sam język.

Obecnie rozwijane są cztery kompilatory języka D:

  • DMD - oficjalny kompilator Waltera Brighta. Front-end kompilatora objęty jest zarówno licencją artystyczną, jak i GNU GPL, a jego kod jest rozpowszechniany razem z binariami. Umożliwia to szybkie tworzenie nowych kompilatorów. Dostępne są także źródła back-endu, lecz nie są one objęte żadną otwartą licencją. Kompilator wspiera ograniczoną liczbę systemów operacyjnych oraz platform sprzętowych (w szczególności brakuje obsługi architektury 64-bitowej).
  • GDC - front-end dla kompilatora GCC wykorzystujący kod z DMD. Obecnie jest uznawany za martwy projekt, jednak ostatnio podjęte zostały próby napisania nowego front-endu, który domyślnie wspierać ma eksperymentalną wersję 2.0 języka[5]
  • LDC - front-end dla kompilatora LLVM wykorzystujący kod z DMD. Obsługuje zarówno wersję 1.0, jak i 2.0, a także bibliotekę Tango i platformy 64-bitowe.
  • D Compiler for .NET - eksperymentalny port kompilatora na platformę .NET[6]

Narzędzia programistyczne

D wciąż nie jest wspierany przez wiele środowisk IDE, co może być przeszkodą dla części użytkowników. Dostępne edytory obejmują m.in. Eclipse, SlickEdit, Entice, Designer, emacs, vim, SciTE, Smultron, TextMate, Zeus czy Geany. Vim wspiera zarówno kolorowanie składni, jak i uzupełnianie kodu. Dodatkowy pakiet pozwala na pracę w TextMate, a IDE Code::Blocks częściowo obsługuje język, jednak brakuje wciąż takich możliwości, jak uzupełnianie kodu i refaktoryzacja.

Istnieją co najmniej dwie aktywnie rozwijane wtyczki dla języka D dla platformy Eclipse: Descent and Mmrnmhrm.

Ponadto, powstają otwarte środowiska napisane w całości w D (np. Poseidon), które posiadają wszystkie niezbędne opcje.

Aplikacje D mogą być analizowane debugerami stworzonymi dla C/C++, np. GDB i WinDbg, lecz z ograniczoną obsługą bardziej zaawansowanych możliwości języka. Pełną obsługę oferuje debuger Ddbg w Windows i może być używany z zewnętrznymi środowiskami programistycznymi lub za pomocą wiersza poleceń. Komercyjny ZeroBUGS dla Linuksa eksperymentalnie obsługuje D oraz posiada własny interfejs użytkownika.

Problemy i kontrowersje

Dwie biblioteki standardowe

Biblioteka standardowa D nosi nazwę Phobos. Część programistów ze społeczności D uważa, że jest ona zbyt uproszczona oraz posiada wiele nieścisłości, dlatego rozpoczęli prace nad alternatywną biblioteką Tango. W D 1.0 obie biblioteki są ze sobą wzajemnie niekompatybilne, gdyż używają innych odśmiecaczy pamięci, mechanizmów wielowątkowości itd. Obecność dwóch równie popularnych bibliotek prowadzi do wielu problemów z przenośnością: część pakietów korzysta z Tango, inne z Phobosa.

Problem jest w dużej mierze rozwiązany w D 2.0, w którym powstało jednolite środowisko uruchomieniowe druntime, na które obie biblioteki zostaną przeportowane, dzięki czemu stanie się możliwe ich jednoczesne wykorzystanie. Obecnie (styczeń 2010) Phobos zakończył już proces migracji. W dającej się przewidzieć przyszłości język będzie mieć dwie konkurujące biblioteki standardowe, lecz od wersji 2.0 będą one ze sobą kompatybilne na podstawowym poziomie, oraz współdzielić pewne podstawowe funkcje (np. interfejs tablic asocjacyjnych czy interfejs zarządzania pamięcią).

Nieukończona obsługa bibliotek współdzielonych

Problem obsługi bibliotek współdzielonych związany jest z działaniem kompilatorów, nie z samym językiem.

Kompilator DMD ma problemy z tworzeniem bibliotek współdzielonych na systemach Unix. Uniksowy format ELF jest wspierany jako rozszerzenie kompilatora GDC. W systemach Windows biblioteki DLL są poprawnie obsługiwane oraz możliwe jest przekazywanie obiektów kontrolowanych przez odśmiecacz pamięci do funkcji C. Występują jednak pewne ograniczenia związane z użyciem obiektów. Związane jest to z mechanizmem automatycznego zarządzania pamięcią, który stosuje D.

W środowisku D istnieje tendencja do kompilowania statycznie całego programu, wraz z optymalizacją globalną oraz międzyproceduralną, co w przypadku bibliotek współdzielonych jest wysoce utrudnione. Kompilator DMD działa bardzo szybko[potrzebny przypis], dlatego równoczesne kompilowanie wielu plików w jednym przebiegu nie stanowi istotnego problemu.

Przykładowy program

Prosty program wypisujący argumenty, z jakimi został wywołany:

import std.stdio;
int main(char[][] args)
{
   foreach(i, a; args)
      writefln("args[%d] = '%s'", i, a);
   return 0;
}

Linki zewnętrzne

  1. Changelog. [w:] D Programming Language 1.0 [on-line]. Digital Mars. [dostęp 31 grudnia 2012]. (ang.).
  2. Changelog. [w:] D Programming Language 2.0 [on-line]. Digital Mars. [dostęp 31 grudnia 2012]. (ang.).
  3. D 1.0 changelog (older versions). (ang.).
  4. D 2.0 changelog. (ang.).
  5. Reaktywacja projektu GDC
  6. http://www.infoq.com/news/2009/05/D-Source