Să ne imaginăm chimia fără Sistemul Perioadei lui Mendeleev (1869). Câte elemente trebuia să ții minte, în ce ordine aleatorie... (Atunci - 60.)
Pentru aceasta, este suficient să te gândești la unul sau mai multe limbaje de programare simultan. Aceleași emoții, aceeași zarvă creativă.
Iar acum putem experimenta emoțiile chimistilor din secolul XIX, când li s-au prezentat toate cunoștințele lor, și câteva în plus, într-un singur tabel periodic.

Cartea „Matrioșka C. Sistem stratificat de limbaj de programare” prezintă toate unitățile limbajului C ca pe o palmă. Acest lucru permite ordonarea lor, corectarea informațiilor învechite și chiar clarificarea însăși a conceptului de program.
Astăzi, informațiile despre programare au nevoie de sistematizare chiar mai mult decât elementele chimice de acum 150 de ani.
Prima necesitate - predarea. Mendeleev a început să creeze sistemul său când a fost confruntat cu întrebarea - de la ce element să înceapă lecțiile: O, H, N, He, Au... În acest timp, lui i-a fost mai ușor - el preda chimie celor mai buni - studenții Universității din Sankt Petersburg. Iar programarea deja se predă în școală și în curând va începe și în grădinițe.
A doua necesitate - abordarea științifică. Cu ajutorul Sistemului Perioadei au fost descoperite noi elemente și corectate informațiile despre cele vechi. A ajutat la crearea modelului atomului (1911). Și așa mai departe.
A treia necesitate - clarificarea conceptului de program.
Programarea modernă este blocată cu un picior în anii '50 ai secolului XX. Atunci programele erau simple, iar mașinile și limbajele de mașină - complexe, așa că totul se învârtea în jurul mașinilor și limbajelor.
Acum totul este invers: programele sunt complexe și primordiale, limbajele sunt simple și secundare. Aceasta se numește abordarea aplicațională, care pare familiară tuturor. Dar studenții și dezvoltatorii continuă să fie convinși că totul este la fel ca înainte.
Ceea ce ne aduce înapoi la prima lecție a privat-docentului Mendeleev. Ce să spunem studenților de anul întâi? Unde este adevărul? Aici este întrebarea.
Cartea „Matrioșka C. Sistem stratificat de limbaj de programare” oferă răspunsul său. Însă aceasta se adresează nu doar studenților, ci și programatorilor pregătiți, deoarece căutarea adevărului și schimbarea viziunii asupra lumii ar trebui să vină tocmai de la ei, adică de la noi.
Urmează o scurtă prezentare a cărții.
1. Introducere
În 1969 a fost creat limbajul C, care a devenit un limbaj de programare fundamental și rămâne astfel de 50 de ani. De ce este așa? În primul rând, pentru că C este un limbaj aplicat , care conferă programelor un aspect uman în loc de asembler mașină.Această realizare a fost consolidată de limbajele din familia C: C++, JavaScript, PHP, Java, C# și altele. În al doilea rând, este un limbaj concis și frumos.
Cu toate acestea, limbajul C este adesea confundat cu asamblorul, complicând și distorsionând astfel percepția sa. O altă extremitate este impunerea unei anumite „filozofii” asupra limbajului: procedurale, orientate pe obiect, funcționale, compilate, interpretate, tipizate etc. Aceasta adaugă emoții, dar nu ajută la o mai bună descriere a limbajului.
Adevărul se află la mijloc, și anume pentru limbajul C — strict la mijloc între percepția filozofică și cea mașinală.
Limbajul C nu este autonom, el se supune vorbirii obișnuite, și în același timp — controlează limbajul asamblor. Această poziție descrie Modelul de vorbire al programului, conform căruia programul este divizat în trei tipuri subordonate: vorbire, cod, comandă. Limbajul C este responsabil pentru al doilea, tipul cod.
Definind locul limbajului în program, putem ordona informațiile despre acesta, ceea ce face Sistemul stratificat al limbajului programului, prezentând limbajul C în spiritul sistemului lui Mendeleev — pe o singură pagină.
Sistemul este construit având în vedere comunicarea limbajelor aplicate, care derivă din subordonarea lor lingvistică. Un set de unități Matryoshka C permite descrierea și compararea diferitelor limbaje, creând o serie de Matryoshka: C++, PHP, JavaScript, C#, MySQL, Python etc. Este potrivit și corect că diferitele limbaje sunt descrise prin unități ale limbajului fundamental.
2. CAPITOLUL 1. Modelul de vorbire al programului. C-ul clar
În primul capitol este prezentat modelul de vorbire al programului, care reflectă abordarea aplicată. Conform acestuia, programul are trei tipuri consecutive evidente:
- vorbire — mesajul direct al programatorului care rezolvă o problemă,
- cod — codificarea soluției într-o formă matematică în limbajul C (sau în orice altul)
- și comandă — comenzile mașină directe.
Modelul de vorbire explică de ce C este un limbaj simplu și accesibil. C este construit după chipul și asemănarea discursului nostru uman obișnuit.
Primul tip de program este vorbirea directă a programatorului. Vorbirea corespunde gândirii umane. Cu ajutorul limbajului sunt scrise programe de către programatori începători — inițial în română, apoi traducând pas cu pas acțiunile în limbajul codului. Și anume după acest model a fost creat limbajul C.
Concluziile programatorului, exprimate prin vorbire, se transformă în formă numerică de cod. Această transformare merită să fie numită reflecție, deoarece vorbirea și codul au aceeași natură (reflecție — naștere — rădăcină). Acest lucru este destul de evident, dacă comparăm tipul verbal (stânga) cu tipul de cod (dreapta) al programului.

Este interesant că reflexia se realizează foarte simplu — doar cu două tipuri de expresii.
Cu toate acestea, descrierea modernă a limbajului C (din 1978) nu conține o listă suficientă de denumiri nici pentru descrierea limbajului în general, nici pentru sarcina de reflexie în particular. De aceea, suntem nevoiți să ne ocupăm de creativitate și să introducem aceste denumiri.
Alegerea cuvintelor trebuie să fie precisă și clară. Pentru aceasta a fost necesar un abordare specială, exprimată pe scurt astfel — utilizarea strictă a limbii materne. Pentru englezi, aceasta ar fi fost engleza, dar noi nu suntem englezi. Așa că folosim ceea ce avem și ne străduim să vorbim românește.
Reflecția este realizată prin două tipuri de expresii:
- calcul ((C) — reflectă schimbarea proprietăților unui obiect. Proprietatea obiectului este exprimată printr-un număr, atunci acțiunea asupra proprietății — aceasta este o acțiune asupra numărului — operație.
- subordonare ((S) — reflectă schimbarea ordinii acțiunilor. Proto-tipul S este propoziția complexă subordonată, de aceea majoritatea tipurilor de S încep cu conectori subordonați „dacă”, „altfel”, „până când”, „pentru”. Alte tipuri de S le completează.
Apropo, poți crede că în descrierea C nu există un nume pentru expresiile de calcul — ele sunt numite pur și simplu „expresii”? După asta nu va mai mira absența unui nume și a unei unități pentru tipul subordonare, și în general, sărăcia în ceea ce privește numele, definițiile și generalizările. Totul pentru că renumitul K/R ("Limba C", Kernighan/Ritchie, 1978) este o vădire, nu o descriere a utilizării limbajului.
Totuși, ar fi dorit să existe o descriere a limbajului. Prin urmare, aceasta este propusă de Sistemul stratificat al limbajului programului.
3. CAPITOLUL 2. Sistemul stratificat. C Scurt.
Orice descriere trebuie să fie precisă și cât mai concisă. În cazul limbajului programului, o descriere frontală este dificilă.
Iată programul nostru. Acesta este format din module. Modulele sunt compuse din subprograme și colecții (structure). Subprogramele constau din expresii individuale: declarații, calcule, subordonări. Există zece tipuri de subordonări. Subordonările conectează subniveluri și subprograme. De asemenea, sunt mai multe tipuri de declarații. Totuși, declarațiile sunt incluse nu doar în subprograme și subniveluri, ci și în module și colecții. Majoritatea expresiilor constau din cuvinte, care sunt atât de complexe încât de obicei sunt prezentate pur și simplu în două liste - cuvinte de bază și cuvinte derivate, cu care va trebui să ne familiarizăm de-a lungul întregii învățări și aplicări a limbajului. Să adăugăm la asta semnele de punctuație și încă o serie de expresii.
În această prezentare, este dificil de înțeles cine pe cine a întrecut.
Abordarea directă și ierarhică a descrierii limbajului ar fi excesiv de complexă. Căutarea unor căi indirecte duce la descrierea limbajului pe baza naturii sale vorbite și a părții sale de comandă. Astfel a apărut Sistemul Stratificat, care coincide parțial cu Sistemul Perioadelor al lui Mendeleev, care este de asemenea stratificat. Așa cum s-a descoperit după 42 de ani de la publicarea sa (1869), periodicitatea sistemului este legată de straturile electronice (1911, modelul atomului Bohr-Rutherford). De asemenea, Sistemul Stratificat și Sistemul Perioadelor au în comun aranjarea tabelară a tuturor unităților pe o singură pagină. Descrierea unităților limbajului este concisă - doar 10 tipuri de expresii și 8 tipuri de alte unități, dar și conținut și claritate. Deși este neobișnuită pentru prima întâlnire.
Unitățile limbajului sunt împărțite în 6 niveluri:
ordine - rânduri ale tabelului
- sectoare - grupuri speciale de tipuri (părți din prima linie)
- tipuri - celule (nivelul principal de divizare)
- subtipuri - separatori de tipuri (nivel rar)
- tipuri - formule ale unităților în partea de jos a celulei sau separată
- exemple - unitățile în sine (doar pentru cuvinte)
- Exemplele de cuvinte sunt descrise de
dicționar — un subsystem separat, format din cele șase niveluri. Componenta de limbaj a C este destul de evidentă, deși merită descrisă. Pe de altă parte, partea de comandă a limbajului este legată de gestionarea compilării, în cadrul căreia se creează un al treilea tip de program - programul de comandă. Aici ne apropiem de cea mai captivantă parte a limbajului C - frumusețea.
4. CAPITOLURILE URMĂTOARE. Frumos C
4. CAPITOLELE URMĂTOARE. Frumosul Si
Limbajul C se află la baza programării moderne. De ce? În primul rând, pentru că corespunde cel mai fidel limbajului uman. În al doilea rând, pentru că a ocolit frumos limitările prelucrării numerice de către mașină.
Ce anume a propus C? Un tip și un strat.
Cuvântul „tip” este o traducere a cuvântului englezesc „type”, care provine din grecescul „prototypus” — „un model”. În limba rusă, cuvântul „tip” nu transmite esența conceptului exprimat, de asemenea se amestecă cu sensul său funcțional de „tip”.
Inițial, tipul rezolva o problemă pur mașinală de calcul, apoi a devenit pista de decolare pentru apariția limbajelor orientate pe obiect.
Stratul a abordat imediat mai multe probleme — atât mașinale, cât și aplicative. De aceea, analiza va începe cu tipul unitar și va trece la stratul multithread.
Una dintre trăsăturile neplăcute ale programării istorice este că majoritatea conceptelor, inclusiv cele de bază, sunt date fără definiții. „Limbajul de programare (numele rîurilor) are un tip întreg și un tip flotant de numere...” — și au trecut mai departe. Ce este „tipul” (model) — nu trebuie definit, pentru că autorii înșiși nu înțeleg acest lucru pe deplin și îl amână „pentru claritate”. Dacă sunt presați la perete, vor oferi o definiție vague și inutilă. Este foarte convenabil să se ascundă în spatele cuvintelor străine: pentru autorii ruși — în spatele celor englezești (tip), pentru englezi — în spatele celor franceze (subrutină), grecești (polimorfism), latine (încapsulare) sau combinației lor (polimorfism ad-hoc).
Dar acesta nu este destinul nostru. Alegerea noastră este definiții clare în limba rusă pură.
Tip
Tip — este un nume predecedent al unui cuantum, definind 1) proprietățile proprii ale cuantumului și 2) alegerea operațiunilor corespunzătoare acestuia.
Cuvântului „tip” (tip) îi corespunde prima parte a definiției: „proprietățile proprii ale cuantumului”. Dar sensul principal al tipului este în a doua parte: „alegerea operațiunilor pentru cuantumuri”.
Punctul de plecare pentru introducerea tipului în limbajul C este calculul obișnuit, de exemplu, operația de adunare.
Matematica în format pe hârtie, scrisă de mână sau tipărită, nu face distincții semnificative între tipurile de numere, considerându-le de obicei ca fiind reale. Prin urmare, operațiile de prelucrare a acestora sunt precise.
Mașinală Matematica separă strict numerele în întregi și fracționare. Diferitele tipuri de numere sunt stocate diferit în memorie și sunt procesate de diferite instrucțiuni ale procesorului. De exemplu, instrucțiunile de adunare pentru numere întregi și fracționare sunt două instrucțiuni distincte, corespunzând unor noduri diferite ale procesorului. Cu toate acestea, instrucțiunea de adunare pentru argumente întregi și fracționari nu există.
Aplicată matematica, adică limbajul C, separă tipurile de numere, dar unește operațiile: adunarea pentru numere întregi și/sau fracționare este notată cu același semn de acțiune.
O definiție clară a conceptului de model permite să vorbim cu certitudine despre două alte concepte: mărimea și operația.
Mărimea și operația
Mărimea — numărul procesat.
Operația — procesarea valorilor mărimilor inițiale (argumentelor) pentru a obține numărul final (rezultatul).
Mărimea și operația sunt interconectate. Fiecare operație este o mărime, deoarece are un rezultat numeric. Iar fiecare mărime este rezultatul transferului valorii în registrul procesorului/din procesor, adică — rezultatul unei operații. În ciuda acestei interconexiuni, principalul rămâne posibilitatea de a le descrie separat, chiar dacă acest lucru implică repetarea aceluiași cuvânt în diferite secțiuni ale dicționarului, ceea ce se întâmplă în ma3.
Abordarea mașinală a împărțit toate numerele folosite de programator în instrucțiuni și date. În trecut, atât acestea, cât și celelalte erau numere, de exemplu, instrucțiunile erau scrise în coduri numerice. Totuși, în limbajele aplicate, instrucțiunile au încetat să mai fie numere și au devenit cuvinte și semne de acțiune. Numerele au rămas doar „date”, dar continuarea de a le numi astfel este ridicolă, deoarece, trecând de la perspectiva mașinală la cea matematică, numerele sunt mărimi care se împart în initiale (date) și finale (cercetate). „Date necunoscute” ar suna prost.
Instrucțiunile s-au împărțit și ele în două tipuri de acțiuni: matematice și funcționale. Acțiunile matematice sunt operații. Ne vom întoarce la cele funcționale mai târziu.
În limbajele C, operațiile matematice uzuale, atât pe hârtie cât și în mașină, aproape că devin în majoritate multiple.
Operațiile multiple sunt câteva operații cu același nume dar cu aspecte diferite ale argumentelor și acțiuni diferite, dar apropiate ca sens.
Pentru argumentele întregi este o operație întreagă, pentru cele fracționare - una fracționară. Această diferență devine evidentă în cazul operației de împărțire, când expresia 1/2 dă ca rezultat 0, nu 0,5. Această notare nu respectă regulile matematicii pe hârtie, dar limbajul C nu își propune să le respecte (spre deosebire de Fortran) - acesta joacă după propriile. aplicative reguli.
În cazul amestecării numerelor întregi cu cele fracționare se activează unica corectă conversie a valorilor argumentelor — o transformare selectivă a valorii dintr-o formă în alta. De fapt, atunci când se adună un număr întreg cu unul fracționar, rezultatul - este fracționar, astfel încât forma operației apropie operația de conversie a argumentului întreg în valoarea fracționară.
O serie de operații rămân multiple, iar simple. Astfel de operații sunt definite doar pentru un singur tip de argumente: restul împărțirii - argumente întregi, bitwise (operații bit la bit) - numere întregi naturale. Ma3 indică multiplicitatea operațiilor prin semnele (#^) cu indicarea formelor pentru care operația este definită. Aceasta este o proprietate importantă, dar anterior neobservată, a fiecărei operații.
Toate funcțiile sunt operațiuni unitare arbitrare. Excepția o constituie operatorii - funcțiile fără paranteze, incorporate în limbaj (operații de bază).
Asistența
Asistența — acțiunea care însoțește operația.
Dacă privim operația ca pe o acțiune principală, putem distinge două acțiuni însoțitoare care asigură operația și diferă de aceasta. Acestea sunt 1) controlul variabilelor și 2) subordonarea. Această acțiune este numită asistență..
Aici trebuie să ne detasăm și să discutăm separat despre traducerile în limba rusă a manualelor de programare. În textul K/R pentru a scrie acțiuni a fost introdus un nou cuvânt statement (instrucțiune), care a încercat să împartă conceptele comenzii mașină în diferite acțiuni: 1) operație, 2) declarație și 3) subordonare (numită „structuri de control”). Această încercare a fost distrusă de traducătorii ruși, înlocuind „instrucțiune” cu cuvântul „operator”, care:
- a devenit sinonim cu cuvântul mașină „comandă”,
- s-a dovedit a fi sinonim cu sintagma „semn de acțiune”,
- și, de asemenea, a primit un număr nelimitat de semnificații suplimentare. Adică s-a transformat într-o analogie cu articolul englez „umm…”.
Să analizăm acțiunile însoțitoare sau asistențele..
Controlul variabilei
Controlul variabilei (UP) — crearea/închiderea celulelor variabile.
UP se produce implicit în timpul declarației variabilei, care oricum este scrisă din alte motive — pentru a indica modul de valoare. Doar un tip este gestionat explicit. variabile suplimentare folosind funcțiile malloc() și free().
Trebuie menționat că acțiunile implicite sunt mai ușor de scris, deoarece nu necesită să scrii nimic, dar mai greu de înțeles — este mai complicat de luat în considerare și de interpretat.
Subordonare
Subordonare — conectarea/dezicerea secțiunilor stratificate.
Limbajul C a oferit o modalitate diferită de gestionare a ordinii acțiunilor — subordonarea. Aceasta reflectă și dezvoltă o propoziție complexă cu o separare clară între partea principală (propoziția principală) și partea subordonată (secțiunile subnivel/subprogram).
Atât declarația, cât și subordonarea se bazează complet pe conceptul de strat.
Stratul
Stratul — este un set selectiv de expresii limitat la un singur nivel.
Stratul a preluat explicit și implicit îndeplinirea imediată a mai multor sarcini:
- ordonarea programului,
- limitarea vizibilității numelui (implicit),
- gestionarea variabilelor (celule de memorie) (implicit),
- definirea secțiunilor subordonate pentru subordonare,
- definirea funcțiilor și selecțiilor și altele.
În limbajele de mașină nu exista conceptul de strat, așa că acesta nu a apărut nici în C/K/R, iar dacă ceva nu era acolo — introducerea acestuia în cărțile ulterioare ar fi fost o heretică și o gândire liberă. De aceea, conceptul de strat nu a apărut deloc, deși este extrem de util și destul de evident.
Fără strat, nu este posibil să explici concis și clar multe acțiuni și reguli ale programului. De exemplu, de ce simple precum cele trei bani goto sunt proaste, în timp ce cele complicate while sunt bune. Poți doar să blestemi fără putere, așa cum a făcut Dijkstra („calificarea programatorilor este o funcție invers proporțională cu frecvența apariției operatorilor goto în programele lor”. Pe scurt, doar oile folosesc goto. Nivelul de justificare — Dumnezeu.) Adevărat, nu este atât de grav dacă cărțile tale nu trebuie să explice nimic, dar, așa cum am spus deja, aceasta nu este soarta noastră.
De altfel, se poate presupune că Den Ritchie a lăsat `goto` ca o cheie pentru a căuta un anumit concept nenumit, deoarece nu exista nicio necesitate sau frumusețe în expresia `goto`. Totuși, a existat nevoie de o explicație simplă și clară a noilor principii ale limbajului, pe care Ritchie nu dorea să le ofere, și care se bazează pe conceptul de strat.
Abatere
Abatere — modificarea proprietăților obișnuite ale noului nume.
Cea mai importantă abatere este legată de proprietățile stratificate ale programului și este descrisă printr-un cuvânt: „static”, care are diferite semnificații în fiecare dintre tipurile de strat.
5. CEA DIN URMĂ. Comunitatea limbajelor aplicate
Limbajele aplicate sunt imaginate limbaje (care au o imagine, „tipizate”). Ele se bazează pe utilizarea explicită sau implicită a imaginii. Din nou apare o contradicție: o imagine explicită este mai clară, dar mai puțin convenabilă, și invers.

(Structura tabelului încă nu a fost livrată, așa că tabelul este dat ca imagine.)
După C, dezvoltarea limbajelor aplicate a mers pe calea creșterii imaginației lor. Cel mai important pentru înțelegerea unei imagini ridicate este descendentul direct al lui C — limbajul C++. Acesta dezvoltă ideea alegerii arbitrare a operațiunilor pentru valori și o împuternicește pe baza expresiei C `selecție`, care a primit un nou nume — obiect. Totuși, C++ nu este la fel de concis și expresiv ca C, din cauza suprasarcinilor de noi tipuri de selecție și a regulilor asociate cu acestea. Apropo, să discutăm despre „suprasarcină”.
Suprasarcină și polimorfism
Cuvântul „suprasarcină” (overload) — un termen învechit al abordării mecanice, înseamnă crearea operațiunilor multiple.
Programatorii de mașini (de sistem) multiplicitatea operațiunilor ar fi putut irita: „Ce înseamnă acest semn (+): adunarea numerelor întregi, adunarea numerelor fracționate sau, în general, deplasarea?! În vremea noastră, nu se scria așa!” De aici nuanța negativă a cuvântului ales („suprareacție”, „s-a săturat”). Pentru programatorul aplicat, operațiile multiple sunt piatra de temelie, realizarea principală și moștenirea limbajului C, atât de naturale, încât sunt adesea neconștientizate.
În limbajul C++ multiplicitatea s-a extins nu doar la operațiunile de bază, ci și la funcții – atât separate, cât și grupate în clase – metode. Odată cu multiplele metode, a apărut posibilitatea redefinirii acestora în clase extinse, denumită vag „polimorfism”. Combinarea polimorfismului cu suprasarcina a dus la o reacție explozivă, rezultând două tipuri de polimorfism: „adevărat” și „ad-hoc”. A lucra cu acestea poate fi realizat doar prin ignorarea denumirilor atribuite. Drumul către ad este pavat cu denumiri străine.
Anunțul de tip „suprasarcină” este mai bine exprimat prin cuvântul redeclarație — adăugând o declarație a aceleași funcții cu argumente de alt tip.
Anunțul de tip „polimorfism” ar trebui denumit redefinire — o declarație de suprascriere în noua stratificare extinsă a aceleași funcții cu argumente de același tip.
Atunci va fi ușor de înțeles că metodele cu nume identice din tipuri diferite (argumente) – sunt redeclarate, în timp ce un tip este – sunt redefinite.
Cuvintele românești rezolvă.
Pista de decolare
Examinarea conceptelor limbajelor de tip înalt confirmă importanța definirii clare a conceptelor fundamentale. Cu un C corect descris, studiul limbajelor de tip înalt va fi ușor și plăcut.
Acest lucru este deosebit de important pentru limbajele de tip înalt implicite (PHP, JavaScript). Pentru acestea, importanța obiectelor (tipuri compuse) devine și mai mare decât în C++, dar noțiunea de tip devine implicită și greu de prins. Din perspectiva comodității, acestea au devenit mai simple, dar din perspectiva înțelegerii – mai complicate.
Prin urmare, studiul limbajelor de programare ar trebui să înceapă cu limbajul C și să progreseze ulterior în ordinea apariției limbajelor din familia C.
Același lucru se aplică descrierii limbajelor. Limbajele diferite au un set de genuri de unități care se suprapun sau sunt mai reduse decât limbajul C. Numărul de tipuri și exemple poate varia în ambele sensuri: C++ are mai multe tipuri decât C, iar JavaScript – mai puține.
Limba MySQL merită o mențiune specială. Părea că nu are nimic în comun, dar este descrisă excelent prin Matryoshka, iar familiarizarea cu aceasta devine mai rapidă și mai simplă. Ce este important, având în vedere semnificația sa pentru web – „drumul mesei” programării moderne. Și unde e MySQL, sunt și alte SQL-uri. De asemenea, diferitele Fortran-uri, Pascal-uri, Python-uri sunt descrise prin Matryoshka, de îndată ce se poate.
Așadar, ne așteaptă lucruri mărețe – o descriere aplicată a limbajului C și o descriere unitară a limbajelor ce urmează. „Obiectivele noastre sunt clare, sarcinile definite. Să ne apucăm de treabă, tovarăși! (Applauze tumultuoase și îndelungate, transformându-se în ovații. Toți se ridică.)”
Opiniile dumneavoastră vor fi ascultate cu mare atenție, iar ajutorul dumneavoastră în crearea site-ului matryoshka va fi primit cu o imensă recunoștință. Informații mai detaliate despre carte sunt disponibile pe site-ul, ascuns ingenios în Matryoshka C.
Sursa: habr.com
