W Pythonie i najprawdopodobniej w wielu innych językach programowania wspólne struktury danych można znaleźć jako zintegrowaną część języka podstawowego z ich własną dedykowaną składnią. Jeśli odłożymy na bok zintegrowaną składnię list LISP, nie mogę myśleć o żadnym innym znanym mi języku, który zapewnia jakąś strukturę danych nad tablicą jako zintegrowaną część ich składni, chociaż wszystkie (chyba C) wydają się zapewniać je w standardowej bibliotece.
Z perspektywy projektowania języka, jakie są Twoje opinie na temat posiadania konkretnej składni struktur danych w języku podstawowym? Czy to dobry pomysł i czy cel języka (itp.) Zmienia, jak dobry może być wybór?
Edycja: Przykro mi z powodu (najwyraźniej) nieporozumień dotyczących tego, które struktury danych mam na myśli. Mówię o podstawowych i często używanych, ale wciąż nie najbardziej podstawowych. Wyklucza to drzewa (zbyt skomplikowane, niezbyt częste), stosy (zbyt rzadko używane), tablice (zbyt proste), ale obejmuje np. Zestawy, listy i mapy skrótów.
Odpowiedzi:
To zależy od języka.
Niektóre przykłady (nieco skradzione z innych odpowiedzi):
Myślę, że to zależy od celu / ducha / odbiorców twojego języka; jak abstrakcyjny i jak daleko od sprzętu ma być. Ogólnie języki, które obsługują listy jako prymitywy, umożliwiają tworzenie nieskończenie długich list. Podczas gdy niski poziom, taki jak C / C ++, nigdy by ich nie miał, ponieważ nie jest to celem, duch tych języków.
Według mnie zbieranie śmieci odbywa się według tej samej logiki: czy odbiorcy w Twoim języku dbają o dokładne określenie, kiedy i czy pamięć jest przydzielana czy zwalniana? Jeśli tak, malloc / free; jeśli nie, to odśmiecanie.
źródło
malloc
inew
są niedeterministyczne w C / C ++).Perl ma mapy skrótów, a PL / SQL obsługuje rekordy, a ja mam bardzo mgliste wspomnienia o matlabie posiadającym składnię do obsługi wektorów i macierzy o różnych wymiarach (chociaż mogę się mylić w tej kwestii i można argumentować, że są to typy danych, a nie dane struktur ) ... Powiedziałbym, że dobrze jest mieć natywne wsparcie dla bardzo popularnych struktur. Zwykle wydaje się, że tablice i tablice skrótów / tablice asocjacyjne są najczęstszymi strukturami obsługiwanymi natywnie i prawdopodobnie są również najczęściej używane.
Nie zapominaj, że jeśli dodasz natywną obsługę składni dla innych struktur, takich jak drzewa binarne, struktury te zostaną również zaimplementowane przez narzędzia wspierające język (kompilator / środowisko wykonawcze / itp.). Dla ilu strucutres chcesz zbudować wsparcie?
Będziesz musiał wymyślić nową notację dla mniej powszechnie obsługiwanych struktur ... Keep It Simple !.
źródło
Moim ulubionym przykładem jest Lua . Lua ma tylko jeden wbudowany typ danych, „ tabelę ”, ale jego elastyczność i szybkość oznaczają, że faktycznie używasz ich zamiast zwykłych tablic, połączonych list, kolejek, map, a nawet są one podstawą obiektowych funkcji Lua (tj. zajęcia).
Lua jest tak niesamowicie prostym językiem, ale elastyczność struktury danych tabeli czyni go również dość potężnym.
źródło
{}
nie ma[]
, w Lua masz{}
jedno i drugie. Tabele Lua lepiej porównać z listami w Lisp.Nie musisz mieć dedykowanej składni dla każdego typu danych wysokiego poziomu. Na przykład tolerowanie jest
set([1, 2, 3])
(tak jak w Pythonie 2.x) zamiast{1, 2, 3}
.Ważną rzeczą jest, aby mieć jakiś wygodny sposób do budowy struktury danych na wysokim poziomie. To, czego chcesz uniknąć, to kod:
która denerwuje mnie bardzo, gdy używam
std::vector
,std::set
orazstd::map
w języku C ++. Na szczęście nowy standard będzie miałstd::initializer_list
.źródło
Moim zdaniem jest to niesamowicie prosty dodatek, który może przydać się zaskakująco często, przynajmniej jeśli jest wykonany ostrożnie - tj. Co najwyżej w przypadku krotek, list, map i zestawów, ponieważ mają one dobrze rozpoznane literały.
someBracket {expr ','} someBracket
lubsomeBracket {expr ':' expr ','} someBracket
, z pewnymi martwymi prostymi dodatkami, jeśli chcesz rzeczy takich jak opcjonalne przecinki końcowe. W literały pływak może łatwo być dłuższy w gramatyce.{1, 2}
).add
/.append
/.setItem
jeden raz dla podanych wyrażeń z tym (tymi) wyrażeniem (-ami) jako argumentami”.źródło
Clojure jest seplenieniem, ale wspiera
źródło
Im więcej struktur danych masz w samym języku, tym trudniej będzie się go nauczyć. Może to być osobista preferencja, ale ja wolę prostszy język, a wtedy biblioteki mogą dostarczyć wszelkie dodatki.
Języki zaprojektowane dla określonych pól mogą czasami korzystać z wbudowanych w język określonych struktur danych, takich jak Matlab. Ale zbyt wielu może cię przytłoczyć.
źródło
Aby język był naprawdę przydatny, musi wykonywać określone zadania od razu po wyjęciu z pudełka. Ponieważ praktyczne codzienne programowanie wymaga narzędzi, które rozwiązują ich problemy na pewnym ogólnym poziomie. Minimalizm wygląda kompaktowo i fajnie, ale jeśli chcesz zacząć rozwiązywać duże, ale powtarzające się problemy, potrzebujesz poziomu abstrakcji, na którym możesz budować.
Myślę więc, że języki programowania powinny zapewniać obsługę najczęściej używanych struktur danych w składni dla zadań, dla których język jest przeznaczony.
źródło
Ogólnie uważam, że wygodne jest posiadanie literałów do list, zestawów i tak dalej. Ale czasem mnie to wkurza, że nie wiem nic o faktycznej implementacji - powiedzmy - listy Python lub tablicy JavaScript. Jedyne, czego mogę być pewien, to to, że ujawniają dany interfejs.
Jako punkt odniesienia dla ekspresji językowej przyjmuję, jak dobrze potrafi pisać własne struktury danych jako biblioteki i jak wygodnie jest z nich korzystać.
Na przykład Scala zapewnia różne kolekcje z różnymi gwarancjami wdrożenia i wydajności. Wszystkie z nich są zaimplementowane w samej Scali, a składnia ich użycia jest tylko nieco bardziej złożona niż gdyby były wbudowane i miały wsparcie w czasie wykonywania.
Jedyną podstawową strukturą, która naprawdę potrzebuje wsparcia ze strony samego środowiska wykonawczego, przynajmniej w języku zarządzanym, jest tablica: jeśli nie zarządzasz pamięcią, ciężko będzie ci uzyskać kilka sąsiednich bajtów. Każda inna struktura może być zbudowana z tablic i wskaźników (lub odniesień).
źródło
APL (i powiązane współczesne warianty, A +, J i K) mają skalar, wektor i macierz jako najwyższej klasy struktury danych.
Tak, mogą być przestarzałe jako zwykłe warianty tablicy. Ale są też wolne od złożonych deklaracji i nie pochodzą z oddzielnej biblioteki, czują się jak złożone struktury danych, które są pierwszorzędną częścią języka.
źródło
Literały list i map oraz wygodna składnia zamknięcia są podstawowymi cechami języków wysokiego poziomu.
Różnica między tym kodem Java:
i ten kod Groovy:
jest ogromny. Jest to różnica między 40 000 programem liniowym a 10 000 programem liniowym. Składnia ma znaczenie.
źródło
var t = new Thing(foo: 3, bar: 6.3, baz: true);
- tylko 4 dodatkowe znaki.Oczywiście zależy to od zastosowania języka programowania, ale w przypadku języków wyższego poziomu praca z dowolną wspólną strukturą danych powinna być jak najwygodniejsza. Przykłady można znaleźć na liście abstrakcyjnych typów danych w Wikipedii. Znalazłem następujące podstawowe zasady (ale chciałbym też usłyszeć inne opinie):
Możesz emulować dowolną strukturę z dowolną inną strukturą - zależy to tylko od tego, jak łatwy i przejrzysty język programowania na to pozwala. Na przykład:
Większość języków zapewnia co najmniej jeden typ dla uporządkowanych sekwencji, jeden dla map jednowymiarowych i jeden dla map wielowymiarowych, ograniczony do funkcji. Osobiście często brakuje mi zestawów i uporządkowanych struktur wielowymiarowych w językach takich jak Perl, PHP, JavaScript, Lua ... ponieważ ich emulowanie nie jest wystarczająco wygodne.
źródło
Myślę, że złym pomysłem jest posiadanie zbyt wielu uprzywilejowanych typów danych, które mają specjalną składnię. To niepotrzebnie komplikuje składnię języka, utrudniając czytanie kodu, utrudniając początkującym naukę i utrudniając opracowanie narzędzi dla języka.
Można zrobić wyjątek dla niewielkiej liczby bardzo popularnych typów struktur danych. Prawdopodobnie pozwoliłbym maksymalnie:
Wszystko, co jest bardziej wyrafinowane niż to, powinno prawdopodobnie zostać pozostawione bibliotekom do obsługi, używając normalnej składni języka dla niestandardowych typów danych.
W szczególności rzeczy takie jak drzewa czerwone / czarne, kolejki priorytetowe itp. Mają całkiem sporo możliwych opcji implementacji, więc nie jest rozsądne upiec konkretną implementację w języku podstawowym. Lepiej pozwolić ludziom wybrać najbardziej odpowiednie wdrożenie dla ich sytuacji. Przykłady opcji implementacji, których projektant języka może nie chcieć ograniczać:
źródło