Jakich języków należy się nauczyć, aby zrozumieć różne podejścia i koncepcje? [Zamknięte]


172

Kiedy wszystko, co masz, to przecinaki do śrub i butelka wódki, wszystko wygląda jak zamek w drzwiach przystani Wolf Blitzera. (Zastąp to młotkiem i gwoździem, jeśli nie czytasz xkcd)

Obecnie programuję Clojure, Python, Java i PHP, więc jestem zaznajomiony ze składnią C i LISP, a także ze spacjami. Znam systemy imperatywne, funkcjonalne, niezmienne, OOP i kilka typów i inne rzeczy. Teraz chcę więcej!

Jakie języki mają inne podejście i byłyby przydatne w praktycznym wyborze narzędzi lub w zrozumieniu teoretycznym?

Nie mam ochoty uczyć się innego języka funkcjonalnego (Haskell) ani innego imperatywnego języka OOP (Ruby), ani nie chcę ćwiczyć niepraktycznych zabawnych języków, takich jak Brainfuck.

Jedną z bardzo interesujących rzeczy, które znalazłem, są monoikoniczne języki oparte na stosie, takie jak Factor.

Dopiero gdy czuję, że rozumiem większość pojęć i mam odpowiedzi na wszystkie moje pytania, chcę zacząć myśleć o moim własnym języku zabawek, aby uwzględnić wszystkie moje osobiste preferencje.


3
Dałbym +1 dla samego odniesienia xkcd, ale pytanie też jest interesujące.

63
Wydajesz się być odnoszącym sukcesy programistą, reszta jest przyrostowa. Nie próbując być kutasem, ale ... jak wygląda twoje życie pod względem finansowym, związanym z relacjami, zdrowiem, zabawą, hobby? Być może teraz jest czas, aby zająć się niektórymi z tych rzeczy. Nie sądzę, abyś musiał znać więcej niż kilkanaście języków naraz. Jeśli zarabiasz na używaniu jednego - naucz się tego. Jeśli chcesz napisać książkę o jednym - naucz się tego. Poza tym masz dobrą bazę programistyczną. Po co uczyć się czegoś (np. J - moja opinia :)), czego na poważnie (czytaj make $) nie użyjesz nigdzie? Nie bądź najfajniejszym hakerem na cmentarzu.
Hamish Grubijan

6
Tak, odnoszę sukcesy jako programista według własnych standardów. Obecnie nie zarabiam dużo pieniędzy, ale hej, mam 19 lat. Inwestuję czas we wszystkie te punkty i nie tylko, ale w programowaniu znajduję zarówno hobby, jak i zabawę. Chcę też powiedzieć, że istnieje różnica między rozumieniem języka a jego opanowaniem. Wystarczy mi opanowanie Pythona i Clojure. Chcę zrozumieć inne dostępne opcje, ponieważ poprawi to mój kod, pomoże mi zrozumieć mój komputer i pomoże mi zdefiniować własny język programowania.
Pepijn,

5
Widziałeś Programmers.SE ? Odpowiada to rodzajowi pytań, które są tam lepiej zadawane.

Odpowiedzi:


287

Kwestie praktyczności są wysoce subiektywne, więc po prostu powiem, że nauka różnych paradygmatów językowych pomoże ci tylko uczynić cię lepszym programistą. Co jest bardziej praktyczne niż to?

Funkcjonalne, Haskell - wiem, że powiedziałeś, że nie chcesz, ale naprawdę powinieneś to przemyśleć. Udało ci się uzyskać funkcjonalną ekspozycję dzięki Clojure, a nawet Pythonowi, ale nie doświadczyłeś tego w pełni bez Haskella. Jeśli naprawdę jesteś przeciwko Haskellowi, dobrym kompromisem jest ML lub OCaml.

Deklaratywny, Datalog - Wiele osób poleciłoby Prolog w tym slocie, ale myślę, że Datalog jest czystszym przykładem języka deklaratywnego.

Array, J - dopiero co odkryłem J, ale uważam, że jest to wspaniały język. Przekręci twój umysł w precla. Podziękujesz za to J.

Stack, Factor / Forth - Factor jest bardzo potężny i planuję jak najszybciej go zagłębić. Forth jest dziadkiem języków stosu, a jako dodatkowy bonus można go łatwo wdrożyć samodzielnie. Jest coś do powiedzenia na temat uczenia się poprzez wdrażanie.

Dataflow, Oz - myślę, że wpływ Oz rośnie i będzie wzrastał tylko w przyszłości.

Oparty na prototypach, JavaScript / Io / Self - Self jest dziadkiem i ma duży wpływ na każdy język oparty na prototypach. To nie to samo, co OOP oparte na klasach i nie powinno być traktowane jako takie. Wiele osób przychodzi do języka prototypowego i tworzy system zajęć ad hoc, ale jeśli Twoim celem jest poszerzenie umysłu, to myślę, że to błąd. Użyj języka w pełni. Czytaj organizowania programów bez klas dla idei.

Expert System, CLIPS - zawsze to polecam. Jeśli znasz Prolog, prawdopodobnie będziesz miał przewagę w przyspieszaniu, ale jest to zupełnie inny język.

Frink - Frink to język ogólnego przeznaczenia, ale słynie z systemu konwersji jednostek. Uważam, że ten język jest bardzo inspirujący w swoim nieustającym dążeniu do bycia najlepszym w tym, co robi. Poza tym ... to naprawdę fajne!

Typy funkcjonalne + opcjonalne, Qi - Mówisz, że masz doświadczenie z niektórymi systemami typów, ale czy masz doświadczenie z systemami typu „skinnable *”? Nikt nie ma ... ale powinien. Qi jest pod wieloma względami jak Lisp, ale System typów zaskoczy Cię.

Aktorzy + tolerancja błędów, Erlang - Model procesu Erlanga jest bardzo popularny, ale jego mechanizmy odporności na błędy i zamiany kodów na gorąco zmieniają grę. Nie dowiesz się zbyt wiele o FP, czego nie nauczyłbyś się z Clojure, ale jego funkcje FT sprawią, że będziesz się zastanawiać, dlaczego więcej języków nie może tego zrobić dobrze.

Cieszyć się!


8
+1 - świetna odpowiedź.
duffymo

2
Dziękuję za wskazanie mi tylu języków do nauki.

2
Dodałbym Erlanga do programowania opartego na aktorach i Fortress do programowania równoległego.
nickik

2
+1 za hot swap Erlanga i rozpoznanie tolerancji błędów
Mic

14
Brak montażu? Dobrze jest wiedzieć, jak działają procesory, aby dowiedzieć się, jaki kod lubią.
Nick T

33

A co z Prologiem (dla unifikacji / cofania itp.), Smalltalk (dla "wszystko jest wiadomością"), Forth (reverse polish, interpretatory wątkowe itp.), Scheme (kontynuacje)?

Nie język, ale Sztuka Protokołu Metaobiektów to przykuwająca uwagę rzecz


Popraw mnie, jeśli się mylę, ale myślę, że Python sortof już wykonuje kontynuacje. I z tego, co przeczytałem, wolę uczyć się Factor i Objective-C niż Forth i Smalltalk, ale może tam pójdę na skróty.
Pepijn

1
@pepijn, Python nie ma kontynuacji pierwszej klasy (chociaż pracuję nad hackowaniem kodu bajtowego, aby go sfałszować)
aaronasterling

1
Objective-C czerpie z Smalltalk, ale myślę, że prawdziwym wnioskiem z ST jest dynamizm samego środowiska.
John Cromartie

33

Popieram Haskella. Nie myśl „Znam Lispa, więc znam programowanie funkcjonalne”. Słyszałeś kiedyś o klasach typu? Algebraiczne typy danych? Monady? „Nowoczesne” (mniej więcej - przynajmniej nie starsze niż 50 lat;)) języki funkcjonalne, zwłaszcza Haskell, odkryły mnóstwo bardzo przydatnych nowych koncepcji. Klasy typów dodają polimorfizm ad hoc, ale wnioskowanie o typie (kolejna rzecz, której języki, które już znasz, nie mają) działa jak urok. Algebraiczne typy danych są po prostu niesamowite, szczególnie do modelowania struktur danych podobnych do drzew, ale działają również dobrze w przypadku wyliczeń lub prostych rekordów. I monady… cóż, powiedzmy, że ludzie używają ich do tworzenia wyjątków, operacji we / wy, parserów, list składanych i wielu innych - w czysto funkcjonalny sposób!

Poza tym cały temat jest na tyle głęboki, że wystarczy go latami;)


„Poza tym cały temat jest na tyle głęboki, że można się nim zająć latami;)” - zastanawiam się, dlaczego miałoby to być dobre? W końcu nasze życie jest ograniczone.
vegai

1
@vegai: Dlaczego miałoby to być złe? Są gorsze sposoby na spędzenie życia niż nauka. I nikt nie powiedział, że trzeba uczyć się latami, żeby właściwie posługiwać się językiem - tylko, że temat nie wyczerpuje się po krótkim czasie. (Zwróć też uwagę na buźkę - ta część nie jest do końca poważna.)

32

Obecnie programuję Clojure, Python, Java i PHP [...] Jakie języki mają inne podejście i byłyby przydatne do praktycznego wyboru narzędzi lub teoretycznego zrozumienia?

do

Wokół jest dużo kodu C - jest to zdecydowanie praktyczne. Jeśli nauczysz się również C ++, jest dużo więcej kodu (a skok jest krótki, gdy znasz C i Javę).

Daje również (lub zmusza do posiadania) doskonałego zrozumienia niektórych zagadnień teoretycznych; na przykład, w pewnym sensie każdy działający program znajduje się w 4-gigabajtowej tablicy bajtów. Wskaźniki w C to po prostu indeksy do tej tablicy - to po prostu inny rodzaj liczb całkowitych. Nie inaczej jest w Javie, Pythonie, PHP, poza tym, że jest ukryta pod warstwą wierzchnią.

Możesz także pisać kod zorientowany obiektowo w C, po prostu musisz być trochę ręcznym na temat vtables i tym podobnych. Kolekcja Portable Puzzle Collection Simona Tathama to świetny przykład dość dostępnego, zorientowanego obiektowo kodu C; jest również dość dobrze zaprojektowany i wart przeczytania dla początkującego / średnio zaawansowanego programisty języka C. Tak też dzieje się w Haskell - klasy typu są w pewnym sensie „po prostu kolejną tabelą”.

Kolejna wspaniała rzecz w C: angażowanie się w pytania i odpowiedzi z wykwalifikowanymi programistami C da ci wiele odpowiedzi, które wyjaśniają C w kategoriach konstrukcji niższego poziomu, co buduje twoją bliższą żelazną bazę wiedzy.

Być może brakuje mi punktu OP - myślę, że tak, sądząc po innych odpowiedziach - ale myślę, że może to być przydatna odpowiedź dla innych osób, które mają podobne pytanie i czytają ten wątek.


1
To wymaga więcej głosów pozytywnych. C jest językiem numer jeden, gdy potrzebujesz lub chcesz od podstaw i zrozumieć działanie maszyny - lub języków programowania wyższego poziomu - od podstaw. Co więcej, jest to również bardzo uniwersalne, kompilatory C istnieją dla (prawie) każdej architektury CPU, jaką kiedykolwiek wymyślono.
dietr

27

Ze strony Petera Norviga:

„Naucz się co najmniej pół tuzina języków programowania. Włącz jeden język, który obsługuje abstrakcje klas (np. Java lub C ++), taki, który obsługuje abstrakcję funkcjonalną (np. Lisp lub ML), taki, który obsługuje abstrakcję składniową (np. Lisp)), taki, który obsługuje abstrakcje deklaratywne specyfikacje (takie jak szablony Prolog lub C ++), takie, które obsługują procedury (takie jak Icon lub Scheme) i takie, które obsługują równoległość (jak Sizal). ”

http://norvig.com/21-days.html



10

W typach jako twierdzeniach / systemach typu zaawansowanego: Coq (myślę, że do tej kategorii należy też Agda).

Coq to dowód pomocniczy wbudowany w funkcjonalny język programowania.

Potrafisz pisać dowody matematyczne, a Coq pomaga zbudować rozwiązanie. Możesz pisać funkcje i dowodzić ich własności.

Ma zależne typy, które same mnie rozwaliły. Prosty przykład:

concatenate: forall (A:Set)(n m:nat), (array A m)->(array A n)->(array A (n+m))

jest sygnaturą funkcji, która łączy dwie tablice o rozmiarze n im elementów A i zwraca tablicę o rozmiarze (n + m). Nie skompiluje się, jeśli funkcja tego nie zwróci!

Opiera się na rachunku konstrukcji indukcyjnych i ma za sobą solidną teorię. Nie jestem wystarczająco bystry, aby to wszystko zrozumieć, ale myślę, że warto się temu przyjrzeć, szczególnie jeśli masz tendencję do teorii typów.

EDYCJA: Muszę wspomnieć: piszesz funkcję w Coq, a następnie możesz udowodnić, że jest poprawna dla każdego wejścia, to niesamowite!


Drugi coq. Podczas nauki większości języków nadal możesz używać swoich starych technik, ale coq zmusza cię do napisania kompletnych programów, które zawsze działają.
Bruno Martinez

Próbowałem nauczyć się Coq zeszłego lata, ale zrezygnowałem, ponieważ trudno mi było znaleźć dobrą dokumentację dotyczącą uczenia się i używania go. Jakieś sugestie?

Uczyłem się z kursu na moim uniwersytecie, a potem przeczytałem „Coq'Art: Rachunek konstrukcji indukcyjnych” Nie wystarczy go naprawdę opanować, ale wystarczy go docenić.
Bruno Martinez

6

Jednym z języków, które Jestem zainteresowany do mają bardzo różny punkt widzenia (w tym nowego słownictwa do zdefiniowania elementów języka i radykalnej składni diff) jest J . Haskell byłby dla mnie oczywistym wyborem, chociaż jest to język funkcjonalny, ponieważ jego system typów i inne unikalne cechy otwierają twój umysł i zmuszają do ponownego przemyślenia wcześniejszej wiedzy z programowania (funkcjonalnego).


5

Tak jak Fogus zasugerował ci to na swojej liście, radzę ci również przyjrzeć się językowi OzML / Mozart Wiele paradygmatów, głównie ukierunkowanych na programowanie współbieżne / wieloagentowe.

Jeśli chodzi o współbieżność i rachunek rozproszony, odpowiednik rachunku lambda (który stoi za programowaniem funkcyjnym) nazywa się rachunkiem Pi.

Dopiero zacząłem przyglądać się pewnej implementacji rachunku Pi. Ale już rozszerzyli moje koncepcje informatyki.


5

Programowanie przepływu danych, czyli programowanie oparte na przepływach, jest dobrym krokiem naprzód na drodze. Kilka modnych słów: przetwarzanie równoległe, szybkie prototypowanie, programowanie wizualne (nie tak źle, jak brzmi najpierw).

Artykuły Wikipedii są dobre:

W informatyce programowanie oparte na przepływach (FBP) jest paradygmatem programowania, który definiuje aplikacje jako sieci procesów „czarnych skrzynek”, które wymieniają dane przez predefiniowane połączenia poprzez przekazywanie komunikatów, gdzie połączenia są określane zewnętrznie do procesów. Te procesy czarnej skrzynki można łączyć w nieskończoność, tworząc różne aplikacje bez konieczności wewnętrznej zmiany. FBP jest więc w naturalny sposób zorientowane na komponenty.

Przeczytaj książkę JPM: http://jpaulmorrison.com/fbp/

(Napisaliśmy prostą implementację w C ++ do celów automatyki domowej i jesteśmy z niej bardzo zadowoleni. Dokumentacja jest w trakcie tworzenia).


+1, wierzę, że przepływ danych i programowanie oparte na przepływie (prawdopodobnie także programowanie funkcjonalne) staną się ważną częścią naszej przyszłości wielordzeniowej.

5

Nauczyłeś się wielu języków. Nadszedł czas, aby skupić się na jednym języku i go opanować.


3

być może będziesz chciał wypróbować LabView do programowania wizualnego, chociaż jest to do celów inżynierskich.

niemniej jednak wydaje się, że interesuje cię wszystko, co tam jest, stąd ta sugestia

możesz też wypróbować aplikację Android appinventor do wizualnego tworzenia rzeczy


LabView ma zabawną „składnię”, ale klikanie i przeciąganie całego kodu jest bardzo trudne. Nie polecałbym tego programiście.
Ishtar

To właśnie jest dostarczane z Lego NXT, prawda? Całkowicie mi się nie udało. Jednak dzięki za sugestię.
Pepijn

pochodzi z National Instruments. LabVIEW to graficzne środowisko programistyczne, które zwiększa produktywność naukowców i inżynierów
Belun

2

Bruce A. Tate, biorąc stronę z The Pragmatic Programmer, napisał książkę dokładnie o tym: Siedem języków w siedem tygodni: pragmatyczny przewodnik po nauce języków programowania

W książce opisuje Clojure, Haskell, Io, Prolog, Scala, Erlang i Ruby.


2
Ostrzegamy, że książka jest pełna odniesień do filmów, które najwyraźniej stały się częścią amerykańskiej popkultury. Jeśli nie widziałeś filmów, będziesz się zastanawiać, o co chodzi Tate. Jeśli widzieliście filmy, nadal możecie zniechęcić się ciągłą antropomorfizacją języków programowania lub po prostu nie lubiącymi postaciami (nie lubię Mary Poppins; przypadkowo też nie lubię Rubiego, więc analogia może być na czymś).
Alan Plum

2

Merkury : http://www.mercury.csse.unimelb.edu.au/

Jest to Prolog typizowany, z typami i trybami unikalności (tj. Z określeniem predykatu append(X,Y,Z) oznaczający X dołączony do Y to Z daje jedno Z, biorąc pod uwagę X i Y, ale może dać wiele X / Y dla danego Z). Ponadto nie ma przecięcia ani innych nielogicznych predykatów.

Jeśli chcesz, to do Prologu, tak jak Haskell do Lispa.


1
  1. Programowanie nie obejmuje zadań programistów.
  2. Nowe rzeczy są zawsze interesujące, ale są też bardzo fajne stare rzeczy.

Pierwszym systemem bazodanowym był dla mnie dBaseIII, spędzałem około miesiąca na pisaniu małych przykładów (dBase / FoxPro / Clipper to baza danych oparta na tabelach z indeksami). Potem, w moim pierwszym miejscu pracy, spotkałem MUMPY i rozbolała mnie głowa. Byłem młody i świeży, ale zrozumienie modelu bazy danych MUMPS zajęło mi 2 tygodnie. Był taki moment, jak w komiksach: po 2 tygodniach włączono guzik, a żarówka właśnie się zapaliła. Świnka jest naturalna, niskopoziomowa i bardzo, bardzo szybka. (Jest to niezrównoważone, niesformalizowane drzewo btree bez typów.) Dzisiejsze trendy wskazują drogę do tego: NoSQL, klucz-wartość db, wielowymiarowa db - więc zostało tylko kilka kroków i dochodzimy do świnki.

Oto prezentacja o zaletach MUMPS: http://www.slideshare.net/george.james/mumps-the-internet-scale-database-presentation

Krótki dokument dotyczący hierarchicznej bazy danych: http://www.cs.pitt.edu/~chang/156/14hier.html

Wprowadzenie do MUMPS globals (w MUMPS zmienne lokalne, w skrócie: locals to zmienne pamięci, a zmienne globalne, short: globals to "zmienne db", ustawienie zmiennej globalnej natychmiast trafia na dysk): http: // gradvs1.mgateway.com/download/extreme1.pdf (PDF)


1

Powiedz, że chcesz napisać wiersz miłosny ...

Zamiast używać młotka tylko dlatego, że masz już taki w dłoni, naucz się odpowiednich narzędzi do tego zadania: naucz się mówić po francusku.

Gdy osiągniesz prawie rodzimy poziom mówienia, możesz rozpocząć swój wiersz.


4
Oczywiście będzie to poemat śmieciowy, bo żeby pisać poezję, trzeba mówić znacznie powyżej zwykłego poziomu tubylców. Twoja dziewczyna będzie musiała nauczyć się francuskiego, aby to przeczytać. Chyba że jest już Francuzką, w takim przypadku prawdopodobnie uzna to za żenujące.
John Lawrence Aspden

Pyszna ironia, John, lubię to (przy okazji jestem
Francuzem

1

Podczas gdy nauka nowych języków na poziomie akademickim jest interesującym hobby, IMHO nie możesz naprawdę nauczyć się go używać, dopóki nie spróbujesz zastosować go do rzeczywistego problemu. Więc zamiast szukać nowego języka do nauki, na twoim miejscu najpierw szukałem nowych rzeczy do zbudowania, a dopiero potem szukałem odpowiedniego języka do tego jednego konkretnego projektu. Najpierw wybierz problem, a potem narzędzie, a nie odwrotnie.


1

Każdemu, kto nie był w pobliżu od połowy lat 80-tych, sugerowałbym naukę 8-bitowego języka BASIC. Jest bardzo niskopoziomowy, bardzo prymitywny i programowanie wokół jego otworów jest interesującym ćwiczeniem.

W tej samej linii wybrałbym kalkulator z serii HP-41C (lub emulator, chociaż nic nie przebije prawdziwego sprzętu). Trudno to otoczyć mózgiem, ale warto. TI-57 wystarczy, ale będzie to zupełnie inne doświadczenie. Jeśli uda ci się rozwiązać równania drugiego stopnia na TI-55, zostaniesz uznany za mistrza (nie miał on żadnych warunków warunkowych i żadnych gałęzi poza RST, który przeskoczył program z powrotem do kroku 0).

I na koniec wybrałbym FORTH (wspomniano wcześniej). Ma fajną Lispską rzecz "buduj swój język", ale jest o wiele bardziej surowym metalem. Nauczy Cię, dlaczego Railsy są interesujące i kiedy DSL mają sens, i będziesz miał wgląd w to, co myśli Twój kalkulator inny niż RPN podczas pisania.


1

Postscriptum. Jest to dość interesujący język, ponieważ jest oparty na stosie i jest dość praktyczny, gdy chcesz przelać rzeczy na papier i chcesz albo to zrobić, albo rozwiązać problem, dlaczego tak się nie dzieje.

Erlang. Wewnętrzny paralelizm nadaje mu raczej niezwykły charakter i możesz z tego ponownie nauczyć się przydatnych rzeczy. Nie jestem pewien co do praktyczności, ale może być przydatny w przypadku niektórych zadań szybkiego prototypowania i wysoce nadmiarowych systemów.

Spróbuj zaprogramować układy GPU - CUDA lub OpenCL. To tylko rozszerzenia C / C ++, ale model mentalny architektury jest znowu zupełnie inny od klasycznego podejścia i zdecydowanie staje się praktyczny, gdy trzeba wykonać kilka rzeczywistych liczb.


1

Erlang, Forth i niektóre osadzone prace z językiem asemblera. Naprawdę; kup zestaw Arduino lub coś podobnego i utwórz polifoniczny sygnał dźwiękowy podczas montażu. Naprawdę się czegoś nauczysz.


1

Jest też anic :

https://code.google.com/p/anic/

Ze swojej strony:

Szybszy niż C, bezpieczniejszy niż Java, prostszy niż * sh

anic jest referencyjnym kompilatorem implementacji dla eksperymentalnego, wysokowydajnego, niejawnie równoległego, wolnego od zakleszczeń języka programowania ANI ogólnego przeznaczenia.

Wydaje się, że nie jest już w trakcie aktywnego rozwoju, ale wydaje się, że zawiera kilka interesujących koncepcji (i w końcu wydaje się, że o to ci chodzi).


1

Chociaż nie spełniasz twojego wymagania "innego" - założę się, że Fantom jest językiem, na który powinien spojrzeć profesjonalny programista. Jak sami przyznają, autorzy fantomu nazywają to nudnym językiem. Po prostu przedstawia najczęstsze przypadki użycia Java i C #, z pewną składnią zapożyczoną z języka Ruby i podobnych nowszych języków.

A mimo to udaje mu się mieć własny bootstrapowany kompilator, zapewnia platformę, która ma instalację bez żadnych zewnętrznych zależności, poprawnie pobiera pakiety - i działa na Javie, C #, a teraz w Internecie (przez js).

Może nie poszerzy twoich horyzontów w zakresie nowych sposobów programowania, ale z pewnością pokaże lepsze sposoby programowania.


1

Jedna rzecz, której brakuje mi w innych odpowiedziach: języki oparte na przepisywaniu terminów.

Możesz rzucić okiem na Pure - http://code.google.com/p/pure-lang/ .

Mathematica jest również oparta na przepisywaniu, chociaż nie jest łatwo dowiedzieć się, co się dzieje, ponieważ jest raczej zamknięta.


0

APL, Forth and Assembly.

Baw się dobrze. Weź zestaw robota Lego Mindstorm i RobotC CMU i napisz kod robotyki. Rzeczy dzieją się, kiedy piszesz kod, który musi „brudzić się” i wchodzić w interakcję z prawdziwym światem, którego nie możesz nauczyć się w żaden inny sposób. Tak, ten sam język, ale z zupełnie innej perspektywy.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.