Staram się uczyć nowego języka programowania w regularnych odstępach czasu. Niedawno przeczytałem, jak Lisp i jego dialekty znajdują się na przeciwległym końcu spektrum od języków takich jak C / C ++, co mnie zainteresowało, aby dowiedzieć się więcej na ten temat. Jednak dwie rzeczy są dla mnie niejasne i szukam wskazówek na ich temat:
Czy LISP jest nadal praktykowany / używany w dzisiejszym świecie, czy jest to język starszego typu, taki jak FORTRAN / COBOL? Mam na myśli, że oprócz utrzymania istniejącego kodu, jest on w ogóle wykorzystywany w nowych projektach?
Jaki jest najczęściej używany dialekt? Spotkałem Scheme i Common Lisp jako 2 najbardziej rozpowszechnione dialekty i chciałem poznać Twoją opinię na temat tego, który z nich jest najbardziej uprzywilejowany / przydatny do nauki - i byłbym niezmiernie zadowolony, gdybyś mógł zasugerować jakieś zasoby dla początkującego rangi.
Choć chętnie uczę się języka, który zasadniczo różni się od języków proceduralnych, do których jestem przyzwyczajony, nie chcę inwestować w coś, jeśli jest całkowicie przestarzały - nadal bym się go uczył, gdyby był zawodowo „martwy”, ale tylko z perspektywy akademickiej ...
Odpowiedzi:
Raczej podoba mi się Scheme, jeśli chcesz pracować z JVM, powinieneś sprawdzić Clojure, który jest seplenieniem zaprojektowanym do pracy w JVM. I tak, Lisp wciąż warto nauczyć się, jak potężny może być tak minimalny projekt! Ludzie, którzy stworzyli seplenienie, mieli naprawdę pewne rzeczy. To niesamowite, ile fajnych nowych funkcji współczesnych języków wypaczało się w latach sześćdziesiątych!
W przypadku osadzonego schematu wypróbuj podstęp: http://www.gnu.org/s/guile/
źródło
W odpowiedzi na pytanie 2 „Najczęściej używany dialekt”:
Zależy od tego, jak interpretujesz „Najczęściej używane”. Oto matematyka na serwetki dla niższych granic tego, ile wykorzystują każdy z wybranych dialektów.
Najczęściej napisany kod
Zwycięzca: Scheme lub Common Lisp. Zbyt wiele niewiadomych.
Większość kodu „produkcyjnego”
Zwycięzca: Zgaduję Common Lisp . Myślę, że możemy odpowiedzieć „Tak” na pytanie 1 w oparciu o użycie Common Lisp i Clojure.
Większość użytkowników końcowych
Zwycięzca: Schemat ma najlepszą dolną granicę tutaj, ponieważ w Uncharted istnieją liczby sprzedaży, ale jest dość dyskusyjne.
Wniosek
Podsumowując, uważam, że duże jabłka.
źródło
Tak, ale musisz wiedzieć, gdzie szukać. Ludzie, którzy używają LISP, nie krzyczą zbyt głośno na ten temat, ale jest kilka przykładów kilku głośnych startupów, które wykorzystały go z wielkim skutkiem w ciągu ostatnich 20 lat. Jest również bardzo popularny wśród małych firm w Europie.
To ważne pytanie, ale odpowiedź na nie jest trudna. Odpowiedź może również nie być szczególnie użyteczna: wiele wdrożeń ma określony cel, więc najlepiej wybrać je, jeśli pasują one do konkretnego problemu, a nie na podstawie tego, jak szeroko jest on używany. Zamiast tego opowiem ci trochę o twoich opcjach i możesz sam zdecydować.
LISP jest rodziną języków, a każdy z tych języków ma rodzinę dialektów i implementacji. Zasadniczo dialekty dzielą się na dwa obozy „LISP” i „Schematy”.
LISP: Do niedawna królem był Common LISP. Była to próba ujednolicenia wszystkich różnych LISP-ów i, nie bez uprzejmości, była „C ++” LISP-a. To znaczy, to był OGROMNY język. Miał wszystko. W ciągu ostatnich kilku lat pojawił się Clojure. Clojure to LISP, który działa na wirtualnej maszynie Java i próbuje zakorzenić się w filozofii programowania funkcjonalnego. Tradycyjnie inne LISP były ściśle paradygmatem. Clojure jest interesujący, ponieważ dostaje zarówno najlepsze, jak i najgorsze z LISP i JVM. Wciąż jest dużo gadatliwości języków opartych na Javie i są one dość bezpłatne i łatwe w składni, dzięki czemu ma wiele pokręteł i przycisków do różnych rzeczy, ale mają kilka naprawdęciekawe pomysły dotyczące typów danych, zwłaszcza niektóre praktyczne sposoby, w jakie wymyślili, aby zastosować pomysły z programowania funkcjonalnego.
Schematy: Schematy są ścisłym podzbiorem LISP. Schemat został wynaleziony przez Steele i Sussmana i we wczesnym okresie życia był znany z zastosowania w kursie wykładowym MIT Computing 101. Schemat jest zdefiniowany w „Poprawionym raporcie n n na temat algorytmu języka algorytmicznego (RnRS)”. Tak: mają tam żart z matematyki. Schemat jest znormalizowanym językiem w taki sposób, jak inne LISP. Pomaga to znacznie w przenośności między implementacjami, ale nie jest to srebrna kula. Wysiłki w zakresie standaryzacji były zwykle konserwatywne, a innowacje we wdrożeniach, szczególnie wokół takich rzeczy, jak moduły, bywały zróżnicowane. Istnieje również seria SRFI (Scheme Requests Implementation), która jest podobna do procesu RFC IETF. Ludzie używają go do standaryzacji drobiazgów według potrzeb.
Schematy różnią się od LISP tym, że mają zestaw twardych wymagań, które muszą spełnić, jednym z nich jest „optymalizacja wywołania ogonowego”, która pomaga zwiększyć efektywność rekurencji. Dlatego rekurencyjne style programowania są znacznie bardziej popularne w Schemacie niż w LISP. Schemat również nie jest nieuprzejmy, podobnie jak „C” LISP. Oznacza to, że są to małe języki i powinieneś być w stanie zachować to wszystko na raz.
Obecnie istnieją dwie rodziny schematów: te oparte na piątej wersji (R5RS) i rodziny oparte na szóstej wersji (R6RS). Złożoność R6RS była znacznie większa niż w przypadku któregokolwiek z jego poprzedników i tak wiele implementacji R5RS zdecydowało się go pominąć, mając nadzieję, że R7RS będzie bardziej podobny do R5RS niż R6RS. Proces standaryzacji R7RS jest obecnie w toku i starał się uwzględnić zarówno pragnienia osób wdrażających R5RS, jak i te z ludu R6RS poprzez ujednolicenie małego podstawowego języka w pierwszej grupie roboczej, a następnie zlecenie drugiej grupie roboczej w celu ustandaryzowania większych funkcji. Dzięki temu język będzie miał wydajne i przydatne implementacje zarówno na niewielkim sprzęcie wbudowanym, jak i na bardziej wydajnych maszynach.
Teraz będę bardziej konkretny:
PicoLisp to naprawdę fajny LISP. Jest malutki! Autor napisał to dla siebie i, jak rozumiem, zarabia na tym od lat 80. Jeśli kiedykolwiek będziesz miał okazję uczestniczyć w jego rozmowie, powinieneś to zrobić: jest naprawdę interesujący i naprawdę zna się na swoich rzeczach, a nie dostaniesz nawet najmniejszego powąchania z głównego nurtu lub nudy.
Nie znam implementacji Common Lisp, więc nie będę ich więcej komentował.
Guile jest oficjalnym programem GNU.
Rakieta jest schematem R6RS, ale ostatnio wydaje się, że poszerzyła sieć i próbuje „służyć jako platforma do tworzenia, projektowania i wdrażania języków”.
Kurczak ma być praktycznym programem. Jest oparty na R5RS i kompiluje się do C. To okazuje się naprawdę, naprawdę ważną zaletą, ponieważ sprawia, że korzystanie z istniejących bibliotek C jest absolutnie trywialne. Dlatego Chicken jest prawdopodobnie najbardziej użytecznym schematem zastępującym Perla, Pythona, Ruby itp. Jako codzienny język skryptowy. Jest kilka osób, które korzystały z niego wyłącznie do swoich potrzeb od kilku lat. Ma interaktywny REPL, a także kompilator. Społeczność (zarówno na liście mailingowej, jak i IRC) jest kompetentna, przyjazna i pomocna.
Poszukaj implementacji z dużą ilością modułów: pokazuje to, że jest szeroko użyteczna i oznacza, że prawdopodobnie będzie miała coś, co pomoże w wykonywanym zadaniu.
Poszukaj implementacji z kompilatorem lub przynajmniej czegoś, co nie jest oparte wyłącznie na IDE lub REPL. Wiele implementacji zaprojektowanych do nauczania jest bardzo trudnych w użyciu do skryptów ogólnego przeznaczenia.
Polecam kurczaka, ponieważ tego właśnie używam. Użyłem go w swoich osobistych projektach i wykorzystałem (i obecnie go używam) profesjonalnie.
Schemat nie jest zawodowo martwy, ale być może będziesz musiał zrobić wszystko, aby użyć go w tym kontekście. Coś takiego jak Kurczak jest czymś znacznie więcej niż akademickim zajęciem i może z łatwością objąć prawie wszystkie podstawy języków wysokiego poziomu, których obecnie używasz.
źródło
Naprawdę nie mogę mówić w imieniu wszystkich Lisps, ale Clojure jest obecnie zdecydowanie gorącym i odpowiednim językiem. Grupa użytkowników londyńskiego Clojure, do której pojechałam wcześniej w tym tygodniu, miała ponad 100 uczestników ....
Odkryłem, że jest to bardzo pouczające doświadczenie w nauce Lisp w postaci Clojure w ciągu ostatniego roku (po wielu doświadczeniach z Javą i C #). Głównymi przyczynami tego są:
Wydaje się również, że jest praktycznym wyborem do rzeczywistego wykorzystania produkcyjnego z następujących powodów:
Osobiście znam osoby korzystające z Clojure w kilku bankach inwestycyjnych i startupach. Wybrałem również Clojure jako podstawowy język programowania dla mojego startupu, więc chętnie wkładam pieniądze tam, gdzie są moje usta :-)
źródło
Obecnie uczę się także Lisp (i uwielbiam to). Korzystam z Common Lisp, ale też pomieszałem z SBCL , Arc (uwaga, to jest wersja Lispa Paula Grahama, która, jak wspomniał Vitor Braga, stworzyła sklep Yahoo / Viaweb) i Allegro CL, który jest podobny do Visual Studio dla Lisp (może tworzyć GUI, jednak nigdy go nie używałem).
Jeśli chodzi o zastosowania, Lisp był często używany w Sztucznej Inteligencji, ale szczerze mówiąc, nie jestem pewien, ile innych „ogólnych” zastosowań Lisp. Wiele stron internetowych, które zostały zbudowane w Lisp, zostały pierwotnie napisane w innych językach, więc trudno powiedzieć, że jest on używany do tworzenia stron internetowych (nie mówiąc, że nie jest, ale większe witryny, które go używają, już nie robią ). Po przeprowadzeniu szybkiego wyszukiwania (bardzo szybko) znajduje się lista oprogramowania napisanego w Common Lisp z Wikipedii .
[EDYCJA] Jeśli chodzi o profesjonalne korzystanie z Lisp, istnieją prace, które pozwoliłyby Ci korzystać z Lisp. Nie są tak liczne, jak powiedzmy zadania Java lub C #, ale istnieją. Myślę, że Lisp jest jednym z tych języków używanych w aplikacjach wewnętrznych i może zapewnić przewagę konkurencyjną, której firmy nie chcą rezygnować z reklam, które używają Lisp. Pamiętam, że widziałem post na P.SE, który stwierdził, że Smalltalk jest podobny na arenie finansowej.
Ponadto, pokazując, że potrafisz nauczyć się różnych paradygmatów, może otworzyć więcej drzwi, nawet jeśli nie używasz Lisp w pracy.
[/EDYTOWAĆ]
źródło
Jeśli chcesz nauczyć się Lisp dzisiaj, rzuciłbym okiem na rakietę, która jest szybkim wdrożeniem schematu (no cóż, właściwie trochę odstąpiła od schematu, więc jest teraz własnym dialektem) lub clojure, który korzysta z JVM, na którym działa (więc gazilliony bibliotek są dostępne, a ponadto możesz zmusić go do interakcji z własnym kodem Java).
Nawet jeśli nie nauczysz się go właściwie używać, nauka jest zawsze korzystna: uczysz się nowych sposobów myślenia i radzenia sobie z problemami, nawet w innych językach, po tym, jak opuścisz umysł wokół Lisp.
źródło
Znaczna część backendu Amazon była kiedyś w Lisp, ale teraz została przepisana w C ++, a przynajmniej tak słyszałem (muszę przyznać, że nie mam na to wiarygodnego źródła).
Wieśniak! Sklepy to jeden z klasycznych przykładów aplikacji internetowych Lisp. Od Yahoo! Przechowuje sławę, którą mogłeś słyszeć o Paulu Grahamie . Graham jest jednym z najbardziej znanych zwolenników Lispa i pisze obszernie na ten temat. Możesz przeczytać jego stronę, aby poznać jego punkty.
AutoCAD miał dialekt Lisp dla swojego systemu makr. Nie wiem czy nadal tak jest.
Schemat to czysty język i bardzo elegancki. To chyba mój ulubiony język programowania, więc mogę być stronniczy. Gdybym miał teraz napisać ważną aplikację, prawdopodobnie napisałbym aplikację szkieletową w C, rozszerzyłbym i zdefiniował reguły biznesowe w Schemacie. To pozwala mi korzystać ze Schematu i wykorzystywać C - dla szybkości i czystej dostępności bibliotek dla prawie wszystkiego.
źródło
Znam kilku facetów, którzy robią Lisps w niektórych startupach w Dolinie Krzemowej i wiem, że Amazon.com używa Lisp od samego początku (choć słyszałem, że z jakiegoś powodu zastępują go C ++?)
Ale jedną firmą, na którą trzeba uważać, jest Naughty Dog . Wszystkie ich gry są napisane dialektem Lisp. Początkowo wyrzucili własne, ale używają MZScheme w serii Uncharted.
Założę się, że Common Lisp, Clojure, Scheme i Emacs Lisp są czterema najczęściej używanymi dialektami, a spośród nich podejrzewam, że Schemat jest najczęściej wdrażany. Oczywiście nie mam nic na poparcie tego. :)
Raczej podoba mi się SICP i Mały Schemer, jak sugerują inni, ale sugerowałbym także Land of Lisp , który jest raczej zabawną lekturą. :)
źródło
Myślę, że częściowo zależy to od tego, co chcesz z tym zrobić - jeśli chcesz pogłębić swoją wiedzę na temat różnych koncepcji programowania i stać się lepszym programistą, powiedziałbym, że warto nauczyć się przynajmniej odrobiny Lisp. Jeśli szukasz innego języka do dodania do CV w celu znalezienia pracy z tym językiem, prawdopodobnie chcesz poszukać gdzie indziej. Nie ma zbyt wielu miejsc pracy w Lisp.
Osobiście próbuję użyć SBCL lub nowszej, Clojure (i niektórych Emacs Lisp, ale htat, ponieważ jestem długoterminowym użytkownikiem Emacsa - starałbym się nauczyć Emacs Lisp, gdy spróbuję nauczyć się Lisp). Teraz muszę tylko znaleźć czas na zabawę w tych językach ...
źródło
Nie wiem, czy w LISP jest mnóstwo miejsc pracy, na pewno ich nie widzę. Pamiętam jednak, jak długo czytałem o sondach NASA, w których działały LISP i były w stanie wstawić nowy kod z Ziemi.
Również w Nowym Jorku grupa spotkań clojure jest ogromna. Zgaduję, że jeśli jesteś zainteresowany i przejdziesz do grupy spotkań clojure, możesz znaleźć możliwości nawiązania sieci i znalezienia pracy (nie oferty clojure, ale rzeczy takie jak Java / C ++ / itp.). Wydaje się być absolutnie ogromny w rejonie Nowego Jorku, inne obszary mogą się różnić.
LISP to także inny sposób myślenia. Dodatkowo zarówno LISP, jak i SQL powodują użycie wielu zagnieżdżonych wyrażeń. Użyłem ton SQL i zauważyłem, że LISP ma więcej sensu. Ale jeśli masz problemy z przyzwyczajeniem się SQL do super zagnieżdżonych nawiasów i wyrażeń podczas korzystania z LISP, prawdopodobnie znacznie ułatwi to zrozumienie wyrażeń SQL.
Klasycznym przykładem jest sposób implementacji MAX (a, b, c). Możesz wykonać skomplikowaną funkcję za pomocą szeregu instrukcji if. Lub możesz po prostu powiedzieć
MAX (MAX (a, b), c)
i użyj dwóch prostych zagnieżdżonych wywołań elementu MAX, który dla mnie jest łatwiejszy do odczytania. Chociaż jeśli wydajność stanowi problem, możesz chcieć to zrobić również w drugą stronę, nie zadałem sobie trudu policzenia liczby porównań przy użyciu każdej metody ... Również jeśli wdrażasz MAX za pomocą makra C lub innej metody, która ocenia wyrażeń wiele razy, możesz nie otrzymać oczekiwanego wyniku, ponieważ wyrażenie może być oceniane wielokrotnie, więc uważaj ze skutkami ubocznymi ...
źródło
MAX(MAX(a b) c)
Dwa dodatkowe punkty:
Po pierwsze, Lisp to świetny język do pisania kodu, w którym interakcje między funkcjami lub danymi są często złożone. W wielu popularnych językach, jeśli masz wątpliwości co do tego, dlaczego twój program robi to, co robi, musisz napisać specjalne funkcje, które pozwolą ci zbadać wewnętrzny stan programu. W niektórych językach musisz poczekać na rekompilację kodu. Oczywiście mogą istnieć narzędzia takie jak debuggery, które mogą w tym pomóc. Jednak w Lisp wszystko czego potrzebujesz to sposób na zatrzymanie programu, a następnie zazwyczaj masz dostęp do wszystkiego w Lisp. W Common Lisp czasami po prostu wpisuję ^ C lub dzwonię na
error
w jedną funkcję (która jest jedyną rzeczą, którą należy ponownie skompilować i nie trzeba nic robić, aby ją ponownie skompilować). Po zatrzymaniu programu jestem natychmiast wrzucany do debugera - ale debuger daje mi całą moc Lisp i mogę wyjść z debugera, wywołać określone funkcje itp. Mogę łatwo zbadać dowolną strukturę danych w moim programie. Większość programów powinna dopuszczać podobne praktyki. Lisp nie jest pod tym względem wyjątkowy, ale to, co oferuje, wykracza poza to, co oferuje wiele popularnych języków.Po drugie: jeśli zamierzasz eksperymentować z dowolnym dialektem Lisp, nie zrobiłbym tego bez (a) użycia edytora pasującego do nawiasów i (b) nauczenia się prawidłowego wcięcia Lisp. Dobrym pomysłem byłoby skorzystanie z edytora, który przybliża również odpowiednie wcięcie. Formatowanie kodu w stylu C / C ++ / Java jest zaprojektowane dla języków z mniejszą liczbą nawiasów / nawiasów klamrowych / nawiasów niż Lisp. Ładny styl drukowania Lisp działa dobrze, gdy się go zaznajomisz, i nie kończysz się na nawiasach lub marnujesz połowę miejsca, umieszczając jeden zamykający nawias na linię.
źródło
W tej chwili mam wrażenie, że Lisp jest najczęściej używany w sklepach konsultingowych (nie że sklepy konsultingowe najczęściej go używają).
Praktyczne oprogramowanie jest uważane za nieco lepsze. Głównie dlatego, że ludzie nie są do tego przyzwyczajeni.
Tradycyjnie Schemat jest dość akademickim dialektem Lisp, a Common Lisp był dialektem branżowym.
Lisp jest szczególnie przydatny w przypadku manipulacji symbolicznych i możliwości tworzenia refleksji.
Na przykład kod, który napisałem, aby nauczyć się Lisp, był programem, który konstruował losowe funkcje lambda, oceniał je, a następnie działał na nich, próbując zminimalizować różnicę funkcji względem funkcji docelowej. Wszystko to było bezpośrednią manipulacją. W języku takim jak C ++ lub Java musiałbym wymyślić reprezentację funkcji, którymi mógłby manipulować komputer.
źródło
Chciałbym dodać trochę perspektywy na temat Common Lisp i Scheme. Unikałem clojure z powodu JVM, więc nie mam na to wiele perspektyw.
Schemat to piękny zwięzły, dobrze zdefiniowany język. Podjęło wiele decyzji, które CL musiał podjąć ze względu na dziedzictwo, i przyjęło bardziej czyste podejście. Na przykład zmienne i funkcje znajdują się w tej samej przestrzeni nazw. Domyślny język jest mniejszy i bardziej zwięzły, co dobrze sprawdza się w nauce rzeczy, w których lisp jest dobry, na przykład wywiera nacisk na użycie rekurencji zamiast iteracji, ponieważ domyślnie nie ma pętli iteracyjnych i wymaga optymalizacji wywołania ogona . Schemat ma bardzo interesujący higieniczny system makro, którego nauka jest bardzo ważna. Ale IMO poleciłbym najpierw naukę makr niehigienicznych w stylu CL, z których większość (?) Schematów programowych oferuje przynajmniej jedną implementację, nawet jeśli nie jest to częścią specyfikacji. Ponieważ wydaje się, że bardzo chcesz nauczyć się języka dla nauki, ja ”
Powiedziawszy to, społeczność Scheme jest podzielona i poza kilkoma niewielkimi kieszeniami wydaje się, że jest głównie poświęcona badaniom nad wykonaniem prawdziwej pracy ... Na przykład każdy dialekt ma własnego menedżera pakietów, a pakiety najczęściej nie są przenośne przez dialekty, co jest ogromnym problemem w społeczności schematów.
Z drugiej strony Common Lisp wydaje się być bardziej pragmatycznym podejściem do rozwijania języka. Standard jest taki, że między implementacjami można przenosić dużo kodu lisp, wiele kompilatorów jest szybkich i dobrze zoptymalizowanych. Istnieje duży zestaw pakietów, z których wiele jest przenośnych między implementacjami. I pozornie (stosunkowo) duża liczba prawdziwych produktów powstaje w tym języku. Dzięki powiedzeniu quicklisp zarządzanie pakietami jest dość zbliżone do tego, co można uzyskać w nowoczesnej społeczności, takiej jak np. Ruby lub Node. CL nie jest jednak pozbawiony wad, ma w tym momencie bardzo dużą specyfikację w porównaniu ze schematem, a nawet jego system obiektowy CLOS, coś, co tradycyjnie jest pisane jako biblioteka w Lisps, jest częścią specyfikacji IIRC. I możesz poczuć, że dziedzictwo jest zakorzenione w dużej ilości systemu.
W przeciwnym razie powiedziałem, że nie mogę mówić o clojure, a Emacs Lisp jest wyraźnie właściwym wyborem, jeśli twoim celem jest napisanie rozszerzeń Emacsa, i całkiem wyraźnie nie jest właściwym wyborem dla innego oprogramowania.
TLDR; Jeśli Twoim celem jest nauka, polecam Schemat. Jeśli jednak chcesz stworzyć oprogramowanie, polecam Common Lisp z dwóch głównych wariantów Lisp.
źródło
Wiele się nauczyłem z odpowiedzi. Dziękuję wszystkim, którzy przyczynili się do tej pouczającej rozmowy.
Powinienem wspomnieć o newLISP . Chociaż różni się nieco zarówno od CL, jak i schematu, implementuje wiele bardzo przydatnych funkcji. Uważam, że serwer http, funkcja wielu procesów (Cilk) i funkcje zdalnej oceny są bardzo czyste i łatwe w użyciu.
Pojedynczy plik wykonywalny jest mały, szybki i zawiera wiele fajnych baterii.
źródło
Kolejnym czynnikiem, który należy wziąć pod uwagę przy wyborze dialektu Lisp do nauki, może być liczba i jakość wdrożeń. Jeśli dialekt ma tylko jedną lub dwie implementacje, utkniesz z ich wadami, dopóki nie zostaną naprawione, i zawsze istnieje szansa, że ludzie przestaną dopracowywać implementację. Sam w sobie nie jest to powód, aby nie używać dialektu Lisp z pojedynczą implementacją, ale należy wziąć to pod uwagę. Zaletą Scheme i Common Lisp jest to, że istnieje wiele implementacji tych dialektów. Oba języki opublikowały standardy, więc stosunkowo niedawne implementacje prawdopodobnie uruchamiają ten sam kod. Niektóre z tych wdrożeń istniały już od dłuższego czasu, ale wciąż są w fazie aktywnego opracowywania: są to obecnie wysokiej jakości wdrożenia i wciąż są udoskonalane.
źródło