From fb38fc44951345f0f59bd9dacdb1a27304928822 Mon Sep 17 00:00:00 2001 From: Timur Shemsedinov Date: Thu, 18 Sep 2025 04:09:39 +0300 Subject: [PATCH] Translatyon sync: en, ru, uk --- README.md | 8 +- content/en/1-6-Engineer.md | 6 +- content/en/1-7-Paradigms.md | 12 +- content/en/1-Introduction.md | 6 +- content/en/2-9-Tasks.md | 46 ++++- content/ru/Index.md | 2 +- content/uk/2-6-Function.md | 117 ++++++++++++- content/uk/2-7-Closure.md | 314 ++++++++++++++++++++++++++++++++++- content/uk/2-8-Errors.md | 144 +++++++++++++++- content/uk/2-Basic.md | 22 ++- content/uk/3-6-Graph.md | 105 +++++++++++- content/uk/Index.md | 2 +- 12 files changed, 768 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 7c35124..a2015e6 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,13 @@ ## Multi-paradigm approach in the Software Engineering -[Index EN](content/en/Index.md) | [Оглавление RU](content/ru/Index.md) | [Зміст UK](content/uk/Index.md) | [Obsah CZ](content/cz/Index.md) +| Language | Index | PDF | +| --- | --- | --- | +| English (EN) | [Index](content/en/Index.md) | [Download](release/Metaprogramming-en.pdf) | +| German (DE) | [Inhalt](content/de/Index.md) | [Download](release/Metaprogramming-de.pdf) | +| Russian (RU) | [Оглавление](content/ru/Index.md) | [Download](release/Metaprogramming-ru.pdf) | +| Czech (CZ) | [Obsah](content/cz/Index.md) | [Download](release/Metaprogramming-cz.pdf) | +| Ukrainian (UK) | [Зміст](content/uk/Index.md) | [Download](release/Metaprogramming-uk.pdf) | Generated books are located in _/release_ folder diff --git a/content/en/1-6-Engineer.md b/content/en/1-6-Engineer.md index 6c937ef..45113ba 100644 --- a/content/en/1-6-Engineer.md +++ b/content/en/1-6-Engineer.md @@ -1,3 +1,5 @@ -## 1.6. Software engineer speciality overview +## 1.6. Software Engineer Profession Overview -No translation +Around programming, as around any sphere of human activity, people have managed to build an enormous number of prejudices and misconceptions. The primary source of problems is terminology, as various paradigms, languages, and ecosystems impose their own terminology, which is not only contradictory between each other, but also illogical even within individual communities. Moreover, many self-taught programmers and loners invent unique, incomparable terminology and concepts that duplicate each other. Aggressive marketers also destructively influence the IT industry as a whole, on the formation of worldview and terminology. By twisting obvious things, confusing and complicating concepts, they ensure an inexhaustible avalanche of problems on which the entire software business is sustained. By luring users and programmers to their technologies, industry giants often create very tempting and plausible concepts that ultimately lead to incompatibility, standards wars, and obvious dependence on software platform vendors. Groups that capture people's attention parasitize on their attention and budgets for decades. Driven by pride and vanity, some developers themselves spread questionable, and sometimes deliberately dead-end ideas. After all, making software well is completely unprofitable for the manufacturer. The situation is significantly better in the field of free software and open source, but decentralized enthusiasts are too fragmented to effectively counter the powerful propaganda of industry giants. + +As soon as any technology or ecosystem develops sufficiently to create good solutions on it, it inevitably becomes obsolete or the manufacturer stops supporting it, or it becomes overly complex. In my memory, more than five such technological ecosystems have already changed. diff --git a/content/en/1-7-Paradigms.md b/content/en/1-7-Paradigms.md index 1e79205..d6ef6b2 100644 --- a/content/en/1-7-Paradigms.md +++ b/content/en/1-7-Paradigms.md @@ -1,3 +1,11 @@ -## 1.7. Programming paradigms overview +## 1.7. Programming Paradigms Overview -No translation +A mathematician views a program as a function that can be decomposed (divided) into simpler functions so that the program-function is their superposition. That is, roughly speaking, a program is a complex formula, a data transformer, where the problem conditions are fed as input, and we get the solution as output. Not every programmer is familiar with this point of view, though it's not perfect, it's useful for rethinking one's activities. The opposite point of view is more common, which is easily obtained from programming practice. It consists of writing programs based on the user's representation, from user interface screen designs and from tools, language, platform, and libraries. As a result, we get not a program-function, but a large system of states in which a combinatorial explosion of transitions occurs and whose behavior is unpredictable even for the author, let alone the user. But we cannot immediately reject this seemingly terrible approach. It has a constructive core, and it lies in the fact that not all programs can be implemented in the functional paradigm as data transformers in a short time. Moreover, human activity consists entirely of steps and changes in the states of objects around us according to the principle of step-by-step manipulation of them, and representing it as functions would be quite unnatural for our thinking. + +A paradigm sets a set of ideas and concepts, assumptions and constraints, concepts, principles, postulates, techniques and programming techniques for solving problems on a computer. + +In this section, we will consider some of them superficially, and later in the book there will be a special chapter with a more detailed discussion of each paradigm. There are languages that support one paradigm, and there are multi-paradigm languages. We will pay attention to different languages and differences in the implementation of paradigms in them. + +For a person, it is natural to represent any action as a set of steps or an algorithm - this is the imperative approach. These steps can be either linear or making a decision to move to another step of the plan, instead of executing actions sequentially. Making a decision for a machine is a comparison operation that leads to algorithm branching, giving options (usually two). Actions can be conditionally divided into internal and external. In internal ones, only the processor and memory participate, the action is executed immediately, without waiting, and has a certain result that is available directly at the next step of the algorithm. External actions are calls to external input/output devices (network, disks, other devices), and they require waiting for a response from the device, which will come in a time usually unknown in advance. We send a control signal to peripheral devices about what they need to do and transfer the necessary data to them. Further, we have two options again: either wait for the result, and this will be called blocking input/output mode, or move to the next step of the algorithm without waiting for the result, and this will be non-blocking input/output. Such a division is caused by a significant difference in the duration of internal and external actions. Most external actions are associated with physical operations on the external environment. For example, data transmission over wireless or wired networks, writing or reading from a physical medium, interaction with sensors, relays or actuators. Such operations often have not a digital, but an analog nature, so additional data conversion is required, waiting for a transient process, waiting for the required sensor reading or signal from the device, etc. Input/output devices often have their own controller in which a separate stream of operations is executed, and interaction between the central processor and input/output devices also requires coordination, which takes time and can end unsuccessfully. + +A paradigm offers a generalized model for solving problems, a certain style, patterns, examples of good and bad solutions used for writing program code. diff --git a/content/en/1-Introduction.md b/content/en/1-Introduction.md index df4871d..0aa6a4f 100644 --- a/content/en/1-Introduction.md +++ b/content/en/1-Introduction.md @@ -1,3 +1,7 @@ # 1. Introduction -No translation +Constant rethinking of one's activities, even the simplest ones, should accompany an engineer throughout their life. The habit of writing down one's thoughts in words and refining formulations is very helpful in this regard. This text emerged as my fragmentary notes, written in different years, which I accumulated and critically reviewed dozens of times. Often, I disagreed with myself when re-reading a passage after it had been sitting for some time. Therefore, I refined the text until I agreed with what was written after prolonged periods of material maturation. I set myself the task of writing as concisely as possible and repeatedly rewrote large fragments, finding that they could be expressed more briefly. The structure of the text and table of contents began to emerge after the first year of teaching, but in the tenth year I decided to publish all materials not only as open video lectures, as I had been doing for about five years, but also as text. This allowed everyone from the Metarchy community to participate in shaping the book, quickly find typos and inaccuracies thanks to readers, and for many it's simply more convenient to perceive in book form. The current version can always be found at https://github.com/HowProgrammingWorks/Book, it will be continuously updated. Please send requests for corrections and additions to issues: https://github.com/HowProgrammingWorks/Book/issues in English, new ideas to discussions: https://github.com/HowProgrammingWorks/Book/discussions in any language, and format your additions and corrections as pull-requests to the book repository. + +> Programming is the art and engineering of solving problems using computational technology + +Engineering, because it is designed to extract benefit from knowledge, and art, because programming at the current stage of development, unfortunately, is not limited to knowledge and is forced to resort to intuition and poorly understood personal experience. The programmer's task is not to find a mathematically correct solution, but to find a generalized solution mechanism capable of leading us to finding an acceptable solution in limited time for as large a class of problems as possible. In other words, to find an abstract class of solutions. Not all programming paradigms assume step-by-step solutions, but the physical implementation of computational technology and the nature of human thinking assume step-by-step processes. The complexity lies in the fact that these actions are far from always reducible to machine operations and involve external interaction with input/output devices and sensors, and through them, with the external world and humans. This circumstance creates great uncertainty, which does not allow mathematically rigorous proof of the correctness of the method for solving all problems and, moreover, strictly derive such a solution from axioms, as is characteristic of exact sciences. However, individual algorithms can and should be derived analytically if they are reducible to pure functions. That is, to functions that at any moment for a certain set of input data unambiguously give the same result. A pure function has no history (memory or state) and does not access external devices (which may have such state), can only access other pure functions. Programming inherited from mathematics the ability to find exact solutions analytically, and the computational machine itself functions strictly within the framework of formal mathematical apparatus. But the process of writing program code cannot always be reduced to formal procedures, we are forced to make decisions under conditions of great uncertainty and construct programs engineering-wise. The programmer is limited by the time of program development, so we reduce uncertainty by introducing constructive constraints that are not strictly derivable from the task and are based on the intuition and experience of a particular specialist. Simply put, in the absence of an optimal algorithm, a programmer can solve a problem in any way that gives acceptable results in reasonable time, and which can be implemented in such time while the problem remains relevant. Under such conditions, we must take into account not only the measure of approximation of the solution to the optimal one, but also the programmer's knowledge, mastery of tools, and other available resources. After all, even access to knowledge of ready-made software solutions is limited by copyright, source code ownership rights and documentation, corresponding license restrictions, not only for software products, but also for books, videos, articles, educational materials, etc. All this significantly complicates and slows down the development of the industry, but over time the availability of knowledge irreversibly grows, they seep into free circulation on the network through popularizers, enthusiasts and the free software movement. diff --git a/content/en/2-9-Tasks.md b/content/en/2-9-Tasks.md index 2a37f52..f0f638f 100644 --- a/content/en/2-9-Tasks.md +++ b/content/en/2-9-Tasks.md @@ -1,3 +1,47 @@ ## 2.9. Tasks -No translation +`Task 1.` Let's take an example that we have already considered, but with several errors added to it. Copy this code into a separate file and fix it so that it not only works, but is beautiful and understandable. You can take the code from the book and lectures as a reference. + +```js +const Items = [ + { CENA: 40 } ,{ CENA : 120 },{ + CENA: '505', + }, { CENA: 350 }]; + +For (const ITEM of items){ +console.log(`Price: ${item.price}`); +} +``` + +`Task 2.` Now let's make a function that will calculate the sum of the entire purchase. Give the function a clear name and add such rules: we need to check if the price is a number (using `typeof`), we sum only positive prices, and if we find a non-number or negative number, we throw an error using `throw`. + +In the course of completing the task, search the internet for documentation on `for..of`, `throw`, `console.log`, functions and arrays. It's best to search in MDN (Mozilla Developer Network). + +Make sure the code runs in the command line through node.js or in the browser. + +`Task 3.` Take this data structure and supplement it with products and product groups following the example of those that already exist: + +```js +const purchase = { + Electronics: [ + { name: 'Laptop', price: 1500 }, + { name: 'Keyboard', price: 100 }, + ], + Textile: [{ name: 'Bag', price: 50 }], +}; +``` + +Put the code in a file and output the entire structure to the screen by running the code in node.js or the browser. + +`Task 4.` Write a `find` function that will go through the structure from the previous task and find a product by its name (checking all product groups). Names can be repeated, but this time we are only interested in the first product whose name matches. + +Example of using the `find` function: + +```js +const result = find(purchase, 'Laptop'); +console.log(result); +``` + +Should output: `{ name: 'Laptop', price: 1500 }` + +`Task 5.` Now let's expand the previous task: we need to modify the `find` function so that it returns an array containing all products with the specified name. If none are found, then an empty array. diff --git a/content/ru/Index.md b/content/ru/Index.md index c960f09..55901f8 100644 --- a/content/ru/Index.md +++ b/content/ru/Index.md @@ -86,7 +86,7 @@ 10.6. Асинхронная и параллельная совместимость 10.7. Подход к передаче сообщений и модель акторов 10.8. Асинхронная очередь и асинхронные коллекции - 10.8. Lock-free структуры данных + 10.9. Lock-free структуры данных 11. Дополнительные парадигмы программирования 11.1. Обобщенное программирование 11.2. Событийное и реактивное программирование diff --git a/content/uk/2-6-Function.md b/content/uk/2-6-Function.md index 9c4757a..e7e49a7 100644 --- a/content/uk/2-6-Function.md +++ b/content/uk/2-6-Function.md @@ -1,3 +1,118 @@ ## 2.6. Функція вищого порядку, чиста функція, побічні ефекти -No translation +Оголошення функції (Function definition) — у `JavaScript` це спосіб оголошення функції, який видимий з будь-якого місця в лексичному контексті, в якому оголошена функція, приклад: + +```js +function sum(a, b) { + return a + b; +} +``` + +Функціональний вираз (Function expression) — зв'язування функції з ідентифікатором за допомогою присвоєння, при якому значення буде доступне через ідентифікатор не в усьому лексичному контексті, а тільки після місця присвоєння. Має кілька синтаксичних варіантів: + +Функціональний вираз з іменованою функцією (Named function expression): + +```js +const sum = function sum(a, b) { + return a + b; +}; +``` + +Анонімний функціональний вираз (Anonymous function expression): + +```js +const sum = function (a, b) { + return a + b; +}; +``` + +Стрілкова або лямбда-функція (Arrow, Lambda function): + +```js +const sum = (a, b) => { + return a + b; +}; +``` + +Лямбда-вираз, Функція-стрілка з виразом як тілом (Lambda expression, Arrow function): + +```js +const sum = (a, b) => a + b; +``` + +> Чиста функція (Pure Function) — детермінована функція без побічних ефектів. + +Чиста функція - функція, що обчислює результат тільки на основі аргументів, не має стану і не звертається до операцій введення-виведення. Результат такої функції завжди детермінований і без побічних ефектів (див. побічний ефект). + +> Замикання (Closure) — функція, пов'язана з лексичним оточенням у момент свого створення. + +Якщо повернути функцію `g` з функції `f`, то `g` буде бачити контекст функції `f`, так само, як і свої аргументи. Якщо `f` повертає `g`, то кажуть, що екземпляр `g` замкнув контекст `f`. Замикання — це спосіб, що дозволяє пов'язати функцію з контекстом (з даними або змінними контексту). Замикання дозволяє створити ефект, аналогічний стану об'єкта (набору його властивостей) в ООП. Властивості пов'язані з методами через об'єкт, по суті об'єкт в ООП сам є контекстом зв'язування. Замикання також породжує подібний контекст, але на основі функцій першого класу і лексичного контексту, а не об'єктного. + +За допомогою замикання можна реалізувати функціональне наслідування. + +Приклади: + +```js +const sum = (a) => (b) => a + b; + +const hash = + (data = {}) => + (key, value) => ((data[key] = value), data); +``` + +> Суперпозиція (Superposition) — об'єднання виклику функцій у вирази таким чином, що результат одних функцій стає аргументами інших функцій. + +```js +const expr2 = sum( + pow(mul(5, 8), 2), + div(inc(sqrt(20)), log(2, 7)) +); +``` + +> Композиція (Composition) — створення нової функції об'єднанням простіших. + +```js +const compose = (f1, f2) => (x) => f2(f1(x)); +``` + +```js +// prettier-ignore +const compose = (...funcs) => (...args) => + funcs.reduce((args, fn) => [fn(...args)], args); +``` + +> Часткове застосування (Partial application) + +```js +// prettier-ignore +const partial = (fn, x) => (...args) => fn(x, ...args); +``` + +> Каррування (Currying) + +```js +const result = curry((a, b, c) => a + b + c)(1, 2)(3); +``` + +> Побічні ефекти (Side effects) + +> Функція вищого порядку (Higher-order Function) + +1. Якщо функція передається в іншу функцію як аргумент, то це колбек. +2. Якщо функція повертається як результат, то це фабрика функцій на замиканнях. +3. Якщо функція, що повертається, має ту ж семантику, що й отримана в аргументах, але з додатковою (розширеною) поведінкою, то це функція-обгортка. +4. Рідко буває, що функція, що повертається, не пов'язана з функцією з аргументів, або пов'язана не прямо, а також має іншу семантику і функцією-обгорткою вона не є. +5. Якщо на виході клас або функція-конструктор, то це фабрики класів і прототипів відповідно. + +> Функція-обгортка (Wrapper) + +Функція, яка обгортає іншу функцію (іноді об'єкт, інтерфейс або функціональний об'єкт), додаючи їй додаткову поведінку. Можна обгорнути цілий API інтерфейс і навіть асинхронну функцію разом з колбеками (якщо відомий контракт). + +```js +const sum = (a, b) => a + b; + +console.log(`Add nums: ${sum(5, 2)}`); +console.log(`Add float: ${sum(5.1, 2.3)}`); +console.log(`Concatenate: ${sum('5', '2')}`); +console.log(`Subtraction: ${sum(5, -2)}`); +``` diff --git a/content/uk/2-7-Closure.md b/content/uk/2-7-Closure.md index 237500c..326abf5 100644 --- a/content/uk/2-7-Closure.md +++ b/content/uk/2-7-Closure.md @@ -1,3 +1,315 @@ ## 2.7. Замикання, функції зворотного виклику, обгортки та події -No translation +> Замикання (Closure) + +```js +const add = (x) => (y) => { + const z = x + y; + console.log(`${x} + ${y} = ${z}`); + return z; +}; +``` + +```js +const res = add(3)(6); +console.log(res); +``` + +```js +const add = (x) => (y) => x + y; +``` + +> Рекурсивне замикання (Recursive closure) + +```js +const add = (x) => (y) => { + const z = x + y; + console.log(`${x} + ${y} = ${z}`); + return add(z); +}; +``` + +```js +const add = (x) => (y) => add(x + y); +``` + +```js +const a1 = add(5); +const a2 = a1(2); +const a3 = a2(3); +const a4 = a1(1); +const a5 = a2(10); +console.log(a1, a2, a3, a4, a5); +``` + +> Ланцюжок функцій (Function chaining) + +```js +const res = add(5)(2)(3)(7); +console.log(res); +``` + +> Абстракція (заміна класу) (Abstraction - class substitution) + +```js +const COLORS = { + warning: '\x1b[1;33m', + error: '\x1b[0;31m', + info: '\x1b[1;37m', +}; + +const logger = (kind) => { + const color = COLORS[kind] || COLORS.info; + return (s) => { + const date = new Date().toISOString(); + console.log(color + date + '\t' + s); + }; +}; +``` + +```js +const warning = logger('warning'); +const error = logger('error'); +const debug = logger('debug'); +const slow = logger('slow'); + +slow('Я повільний логер'); +warning('Привіт'); +error('Світ'); +debug('До побачення!'); +``` + +> Ланцюжок методів об'єкта (Object method chaining) + +```js +const adder = (a) => { + const value = () => a; + const add = (b) => adder(a + b); + return { add, value }; +}; +``` + +```js +const v = adder(3).add(-9).add(12).value(); +console.log(v); +``` + +> Альтернативний синтаксис (Alternative syntax) + +```js +const adder = (a) => ({ + value() { + return a; + }, + add(b) { + a += b; + return this; + }, +}); +``` + +```js +const v = adder(3).add(-9).add(12).value(); +console.log(v); +``` + +> Альтернативний синтаксис (Alternative syntax) + +```js +const adder = (a) => ({ + value: () => a, + add: (b) => adder(a + b), +}); +``` + +```js +const v = adder(3).add(-9).add(12).value(); +console.log(v); +``` + +> Складний приклад (Complex example) + +```js +const adder = (a) => { + let onZerro = null; + const obj = {}; + const value = () => a; + const add = (b) => { + let x = a + b; + if (x < 0) { + x = 0; + if (onZerro) onZerro(); + } + return adder(x); + }; + const on = (name, callback) => { + if (name === 'zero') onZerro = callback; + return obj; + }; + return Object.assign(obj, { add, value, on }); +}; +``` + +```js +const a = adder(3) + .on('zero', () => console.log('Less than zero')) + .add(-9) + .add(12) + .add(5) + .value(); + +console.log(a); +``` + +> Колбек (Callback) + +```js +// Звичайне повернення результату +const sum = (a, b) => a + b; + +// Повернення результату в функцію зворотного виклику +const sum = (a, b, callback) => callback(a + b); +``` + +```js +console.log('sum(5, 2) =', sum(5, 2)); +sum(5, 2, console.log.bind(null, 'sum(5, 2) =')); +``` + +```js +const fs = require('fs'); + +const reader = (err, data) => { + console.log({ lines: data.split('\n').length }); +}; + +fs.readFile('./file.txt', 'utf8', reader); +``` + +> Іменовані колбеки (Named callbacks) + +```js +const fs = require('fs'); + +const print = (fileName, err, data) => { + console.log({ lines: data.split('\n').length }); +}; + +const fileName = './file.txt'; +const callback = print.bind(null, fileName); +fs.readFile(fileName, 'utf8', callback); +``` + +> Реалізація таймера з колбеком (Timer implementation with callback) + +```js +const fn = () => { + console.log('Callback from from timer'); +}; + +const timeout = (interval, fn) => { + setTimeout(fn, interval); +}; + +timeout(5000, fn); +``` + +> Каррування таймера (Timer curry) + +```js +const curry = (fn, ...par) => { + const curried = (...args) => { + if (fn.length <= args.length) return fn(...args); + return curry(fn.bind(null, ...args)); + }; + return par.length ? curried(...par) : curried; +}; +``` + +```js +const fn = () => { + console.log('Callback from from timer'); +}; + +const timeout = (interval, fn) => { + setTimeout(fn, interval); +}; + +const timer = curry(timeout); +timer(2000)(fn); + +const timer2s = timer(2000); +timer2s(fn); +``` + +> Колбеки ітерації (Iteration callbacks) + +```js +const iterate = (array, listener) => { + for (const item of array) { + listener(item); + } +}; + +const cities = ['Київ', 'Лондон', 'Пекін']; + +const print = (city) => { + console.log('City:', city); +}; + +iterate(cities, print); +``` + +> Події (Events) + +```js +const adder = (initial) => { + let value = initial; + const add = (delta) => { + value += delta; + if (value >= add.maxValue) add.maxEvent(value); + return add; + }; + add.max = (max, event) => { + add.maxValue = max; + add.maxEvent = event; + return add; + }; + return add; +}; +``` + +```js +const maxReached = (value) => { + console.log('max value reached, value: ' + value); +}; + +const a1 = adder(10).max(100, maxReached)(-12); + +a1(25); +a1(50); +a1(75); +a1(100); +a1(-200)(50)(30); +``` + +> EventEmitter + +```js +const { EventEmitter } = require('events'); + +const emitter = new EventEmitter(); + +emitter.on('new city', (city) => { + console.log('Emitted city:', city); +}); + +emitter.on('data', (array) => { + console.log(array.reduce((a, b) => a + b)); +}); + +emitter.emit('new city', 'Делі'); +emitter.emit('new city', 'Берлін'); +emitter.emit('new city', 'Токіо'); +emitter.emit('data', [5, 10, 7, -3]); +``` diff --git a/content/uk/2-8-Errors.md b/content/uk/2-8-Errors.md index ec348d8..41a4447 100644 --- a/content/uk/2-8-Errors.md +++ b/content/uk/2-8-Errors.md @@ -1,3 +1,145 @@ ## 2.8. Винятки та обробка помилок -No translation +> Налагодження (Debug) — процес виявлення та усунення помилок у програмному забезпеченні. + +Налагодження реалізують за допомогою виводу повідомлень або інструментів: налагоджувача, профілювальника, декомпілятора, систем моніторингу ресурсів та логування, систем безперервної інтеграції та тестування. + +«Налагодження коду вдвічі складніше, ніж його написання. Тому якщо ви пишете код настільки розумно, наскільки можете, то ви за визначенням недостатньо кмітливі, щоб його налагоджувати.» // Брайан Керніган + +«Якщо налагодження — процес видалення помилок, то програмування має бути процесом їх внесення» // Едсгер Дейкстра + +> Throw + +```js +const isNumber = (value) => typeof value === 'number'; + +const sum = (a, b) => { + if (isNumber(a) && isNumber(b)) { + return a + b; + } + throw new Error('a та b мають бути числами'); +}; +``` + +```js +try { + console.log(sum(2, 3)); +} catch (err) { + console.log(err.message); +} +``` + +```js +try { + console.log(sum(7, 'A')); +} catch (err) { + console.log(err.message); +} +``` + +> Повернення кортежу або структури (Return tuple or struct) + +```js +const sum = (a, b) => { + if (isNumber(a) && isNumber(b)) { + return [null, a + b]; + } + return [new Error('a та b мають бути числами')]; +}; + +console.log(sum(2, 3)); + +console.log(sum(7, 'A')); +``` + +> Колбек (Callback) + +```js +const sum = (a, b, callback) => { + if (isNumber(a) && isNumber(b)) { + callback(null, a + b); + } else { + callback(new Error('a та b мають бути числами')); + } +}; +``` + +```js +sum(2, 3, (err, result) => { + if (err) { + console.log(err.message); + return; + } + console.log(result); +}); +``` + +```js +sum(7, 'A', (err, result) => { + if (err) { + console.log(err.message); + return; + } + console.log(result); +}); +``` + +> Promise + +```js +const sum = (a, b) => + new Promise((resolve, reject) => { + if (isNumber(a) && isNumber(b)) { + resolve(a + b); + } else { + reject(new Error('a та b мають бути числами')); + } + }); +``` + +```js +sum(2, 3) + .then((data) => { + console.log(data); + }) + .catch((err) => { + console.log(err.message); + }); +``` + +```js +sum(7, 'A') + .then((data) => { + console.log(data); + }) + .catch((err) => { + console.log(err.message); + }); +``` + +> Асинхронне викидання (Async throw) + +```js +const sum = async (a, b) => { + if (isNumber(a) && isNumber(b)) { + return a + b; + } + throw new Error('a та b мають бути числами'); +}; +``` + +```js +try { + console.log(await sum(2, 3)); +} catch (e) { + console.log(e.message); +} +``` + +```js +try { + console.log(await sum(7, 'A')); +} catch (err) { + console.log(err.message); +} +``` diff --git a/content/uk/2-Basic.md b/content/uk/2-Basic.md index 5167034..bfe3876 100644 --- a/content/uk/2-Basic.md +++ b/content/uk/2-Basic.md @@ -1,6 +1,10 @@ -## 2. Базові концепти +# 2. Базові концепти -No translation +Нам потрібні коментарі для тимчасового запобігання виконанню або компіляції блоку коду, для зберігання структурованих анотацій або метаданих (інтерпретованих спеціальними інструментами), для додавання TODO або зрозумілих розробнику пояснень. + +> Коментар — це послідовність символів у коді, що ігнорується компілятором або інтерпретатором. + +Коментарі у всіх мовах сімейства `C`, таких як `C++`, `JavaScript`, `Java`, `C#`, `Swift`, `Kotlin`, `Go` тощо, мають однаковий синтаксис. ```js // Single-line comment @@ -13,10 +17,16 @@ No translation */ ``` +Не тримайте в коментарях очевидні речі, не повторюйте те, що і так зрозуміло з самого коду. + +У `bash` (shell-скриптах) та `Python` ми використовуємо знак "номер" (дієз або решітку) для коментування. + ```py # Single-line comment ``` +`Python` використовує багаторядкові рядки як багаторядкові коментарі з виділенням потрійними лапками. Але пам'ятайте, що це рядковий літерал, не присвоєний у змінну. + ```py """ Multi-line @@ -24,14 +34,20 @@ No translation """ ``` +SQL використовує два тире, щоб почати однострочний коментар до кінця рядка. + ```sql select name from PERSON -- comments in sql ``` +HTML-коментарі мають тільки багаторядковий синтаксис. + ```html ``` +В асемблері та множині діалектів LISP ми використовуємо крапку з комою (або кілька крапок з комою) для різних типів коментарів. + ``` -; Single-line comment in Assembler and LISP +; Однострочний коментар в Assembler та LISP ``` diff --git a/content/uk/3-6-Graph.md b/content/uk/3-6-Graph.md index febdc1f..ec5b134 100644 --- a/content/uk/3-6-Graph.md +++ b/content/uk/3-6-Graph.md @@ -1,3 +1,106 @@ ## 3.6. Дерева та графи -No translation +> Матриця суміжності - зберігає зв'язки вершин графа + +``` + 1 +---+ const graph = [ + +--------------+ B +--+ [0, 1, 1, 0, 1], + | +---+ | [1, 0, 0, 1, 0], + | | [1, 0, 0, 1, 0], ++-+-+ 2 | [0, 1, 1, 0, 0], +|| A +----------+ |3 [1, 0, 0, 0, 0], +|+-+ | | ]; + | | | + | +-+-+ | const graph = { + |5 | C | | A: [0, 1, 1, 0, 1], + | +-+-+ | B: [1, 0, 0, 1, 0], + +--+ | | C: [1, 0, 0, 1, 0], + | | | D: [0, 1, 1, 0, 0], + +-+-+ 4 | +-+-+ E: [1, 0, 0, 0, 0], + | E | +------+ D | }; + +---+ +---+ +``` + +> Матриця суміжності у вигляді плоского масиву + +``` + 1 +---+ const graph = [ + +--------------+ B +--+ 0, 1, 1, 0, 1, + | +---+ | 1, 0, 0, 1, 0, + | | 1, 0, 0, 1, 0, ++-+-+ 2 | 0, 1, 1, 0, 0, +|| A +----------+ |3 1, 0, 0, 0, 0, +|+-+ | | ]; + | | | + | +-+-+ | + |5 | C | | + | +-+-+ | + +--+ | | + | | | + +-+-+ 4 | +-+-+ + | E | +------+ D | + +---+ +---+ +``` + +> Матриця інцидентності - зв'язок вершин (рядки) з дугами (стовпці) + +``` + 1 +---+ const graph = [ + +--------------+ B +--+ [1, 1, 0, 0, 1], + | +---+ | [1, 0, 1, 0, 0], + | | [0, 1, 0, 1, 0], ++-+-+ 2 | [0, 0, 1, 1, 0], +|| A +----------+ |3 [0, 0, 0, 0, 1], +|+-+ | | ]; + | | | + | +-+-+ | const graph = { + |5 | C | | A: [1, 1, 0, 0, 1], + | +-+-+ | B: [1, 0, 1, 0, 0], + +--+ | | C: [0, 1, 0, 1, 0], + | | | D: [0, 0, 1, 1, 0], + +-+-+ 4 | +-+-+ E: [0, 0, 0, 0, 1], + | E | +------+ D | ]; + +---+ +---+ +``` + +> Список суміжності - список вершин, а для кожної список суміжних вершин + +``` + 1 +---+ const graph = { + +--------------+ B +--+ A: [], + | +---+ | B: [], + | | C: [], ++-+-+ 2 | D: [], +|| A +----------+ |3 E: [], +|+-+ | | }; + | | | + | +-+-+ | const { A, B, C, D, E } = graph; + |5 | C | | A.push(B, C, E); + | +-+-+ | B.push(A, D); + +--+ | | C.push(A, D); + | | | D.push(B, C); + +-+-+ 4 | +-+-+ E.push(A); + | E | +------+ D | + +---+ +---+ console.dir({ graph }); +``` + +> Список ребер - список з вказівкою ребра як пари вершин + +``` + 1 +---+ const graph = [ + +--------------+ B +--+ [A, B], + | +---+ | [A, C], + | | [B, D], ++-+-+ 2 | [C, D], +|| A +----------+ |3 [A, E], +|+-+ | | ]; + | | | + | +-+-+ | const graph = [ + |5 | C | | { from: A, to: B }, + | +-+-+ | { from: A, to: C }, + +--+ | | { from: B, to: D }, + | | | { from: C, to: D }, + +-+-+ 4 | +-+-+ { from: A, to: E }, + | E | +------+ D | ]; + +---+ +---+ +``` diff --git a/content/uk/Index.md b/content/uk/Index.md index b735669..0e5bac6 100644 --- a/content/uk/Index.md +++ b/content/uk/Index.md @@ -50,7 +50,7 @@ 6.3. Об'єктно-орієнтовані антипатерни 6.4. Функціональні антипатерни 7. Процес розробки - 7.1. Життєвий цикл ПЗ, аналіз предметної областіи + 7.1. Життєвий цикл ПЗ, аналіз предметної області 7.2. Угоди та стандарти 7.3. Тестування: модульне, системне та інтеграційне тестування 7.4. Перевірка коду та рефакторинг