Skip to content

Exam #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions JavaScript/1-object.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
'use strict';

const rome = { name: 'Rome' };
// Робимо спільний об'єкт `rome` незмінним.
const rome = Object.freeze({ name: 'Rome' });

// Створюємо об'єкт `marcus` одразу з потрібними даними, без подальших мутацій.
const marcus = {
id: 1,
name: 'Marcus',
name: 'Marcus Aurelius',
city: rome,
email: '[email protected]',
};
marcus.name = 'Marcus Aurelius';

const lucius = Object.assign({}, marcus, { name: 'Lucius Verus' });
lucius.email = '[email protected]';
// Створюємо `lucius` на основі `marcus` за допомогою spread-синтаксису
const lucius = {
...marcus,
name: 'Lucius Verus',
email: '[email protected]',
};

// Можна "заморозити" і фінальні об'єкти
console.log({ marcus, lucius });
63 changes: 41 additions & 22 deletions JavaScript/2-record.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,31 @@ class Record {
}

static #build(fields, isMutable) {
const fieldSet = new Set(fields);

class Struct {
static fields = fields.slice();
static fields = Object.freeze(fields.slice());
static mutable = isMutable;

static create(...values) {
if (fields.length !== values.length) {
throw new Error('Record arity mismatch');
static create(props) {
for (const field of fields) {
if (!Reflect.has(props, field)) {
throw new Error(`Missing field: ${field}`);
}
}
const obj = Object.create(null);
for (let i = 0; i < fields.length; i++) {
obj[fields[i]] = values[i];
for (const key in props) {
if (!fieldSet.has(key)) {
throw new Error(`Unexpected field: ${key}`);
}
}

const obj = Object.fromEntries(
fields.map(field => [field, props[field]])
);
return isMutable ? Object.seal(obj) : Object.freeze(obj);
}
}
return Struct;
}

static update(instance, updates) {
if (Object.isFrozen(instance)) {
throw new Error('Cannot mutate immutable Record');
Expand All @@ -39,23 +46,35 @@ class Record {
}
return instance;
}

static fork(instance, updates) {
const copy = Object.create(null);
for (const key of Object.keys(instance)) {
copy[key] = Reflect.has(updates, key) ? updates[key] : instance[key];
}
const copy = { ...instance, ...updates };
return Object.isFrozen(instance) ? Object.freeze(copy) : Object.seal(copy);
}
}

// Usage
// Оновлений приклад використання

const City = Record.immutable(['name']);
const User = Record.mutable(['id', 'name', 'city', 'email']);
const rome = City.create('Rome');
const marcus = User.create(1, 'Marcus', rome, '[email protected]');
Record.update(marcus, { name: 'Marcus Aurelius' });
const lucius = Record.fork(marcus, { name: 'Lucius Verus' });
Record.update(lucius, { email: '[email protected]' });
console.log({ marcus, lucius });
const User = Record.immutable(['id', 'name', 'city', 'email']);
const rome = City.create({ name: 'Rome' });
const marcus = User.create({
id: 1,
name: 'Marcus',
city: rome,
email: '[email protected]'
});

const marcusUpdated = Record.fork(marcus, { name: 'Marcus Aurelius' });
const lucius = Record.fork(marcusUpdated, {
name: 'Lucius Verus',
email: '[email protected]'
});

console.log({ marcus, marcusUpdated, lucius });

try {
Record.update(marcus, { name: 'FAIL' });
} catch (err) {
console.error('\nError trying to update immutable record:', err.message);
}
78 changes: 51 additions & 27 deletions JavaScript/3-branch.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,42 @@ class Record {
static immutable(fields) {
return Record.#build(fields, false);
}

static mutable(fields) {
return Record.#build(fields, true);
}

static #build(fields, isMutable) {
const fieldSet = new Set(fields);
class Struct {
static fields = fields.slice();
static fields = Object.freeze(fields.slice());
static mutable = isMutable;

static create(...values) {
if (fields.length !== values.length) {
throw new Error('Record arity mismatch');
}
// Приймаємо об'єкт з іменованими полями замість позиційних аргументів.

static create(props) {
const obj = Object.create(null);
for (let i = 0; i < fields.length; i++) {
obj[fields[i]] = values[i];
for (const field of fields) {
if (!Reflect.has(props, field)) {
throw new Error(`Missing field: ${field}`);
}
obj[field] = props[field];
}

for (const key in props) {
if (!fieldSet.has(key)) {
throw new Error(`Unexpected field: ${key}`);
}
}
return isMutable ? Object.seal(obj) : Object.freeze(obj);
}
}
return Struct;
}

// Оновлює мутабельний екземпляр. Залишається без змін, логіка коректна.

static update(instance, updates) {
if (Object.isFrozen(instance)) {
throw new Error('Cannot mutate immutable Record');
throw new Error('Cannot mutate an immutable Record instance');
}
for (const key of Object.keys(updates)) {
if (Reflect.has(instance, key)) {
Expand All @@ -40,26 +49,41 @@ class Record {
return instance;
}

//Створює новий, незалежний екземпляр (імутабельне оновлення).

static fork(instance, updates) {
const obj = Object.create(null);
for (const key of Object.keys(instance)) {
obj[key] = Reflect.has(updates, key) ? updates[key] : instance[key];
}
return Object.isFrozen(instance) ? Object.freeze(obj) : Object.seal(obj);
const newInstance = { ...instance, ...updates };
return Object.isFrozen(instance)
? Object.freeze(newInstance)
: Object.seal(newInstance);
}

static branch(instance, updates) {
const obj = Object.create(instance);
for (const key of Object.keys(updates)) {
Reflect.defineProperty(obj, key, {
value: updates[key],
writable: true,
configurable: true,
enumerable: true,
});
}
return Object.isFrozen(instance) ? Object.freeze(obj) : Object.seal(obj);
}
// Метод `branch` видалено.

}

module.exports = { Record };

// Приклад використання оптимізованого коду

const User = Record.immutable(['id', 'name', 'email']);
const user1 = User.create({
id: 1,
name: 'Marcus',
email: '[email protected]',
});

const user2 = Record.fork(user1, { name: 'Marcus Aurelius' });

// `user1` залишився незмінним
const user3 = Record.fork(user2, { email: '[email protected]', name: 'Marcus Aurelius Antoninus' });

console.log('User 1:', user1);
console.log('User 2:', user2);
console.log('User 3:', user3);

try {
Record.update(user1, { name: 'FAIL' });
} catch (e) {
console.error('\nSuccessfully caught error:', e.message);
}
Loading