• Каррирование функций в JavaScript
    –1
    вы решали не ту же самую задачу, а ее надмножество

    То есть если моя функция решает ту же задачу, что и функция в статье, плюс может делать что-то ещё, то сравнивать эти функции на одинаковых задачах, которые они обе умеют решать по вашему нельзя? Где логика?))


    именно по этой причине функция partial не попала в ваше сравнение

    Попала, в приведённом списке light-curry примерно настолько же примитивно сделан. Да, сам по себе он быстрее создаёт каррированную функцию, но созданная функция в три раза медленнее такой же, созданной моей библиотекой. Почему то мне кажется, что скорость создаваемой каррированной функции намного важнее, чем скорость её создания, так как она может быть вызвана множество раз (обычно так и случается). Вы так не думаете?

  • Каррирование функций в JavaScript
    –1
    То есть вас просто название смутило? Функционал библиотеки является надмножеством функционала приведённого примера и полностью его покрывает, тоже относится к библиотекам в приведённом вами списке. Почему все они используют название curry вместо partial я не знаю, может они все ошиблись, а может это вы что-то не понимаете.
  • Каррирование функций в JavaScript
    +1
    Ну я вроде дал ссылку на результаты бенчмарков, в чём-то медленнее, в чём-то быстрее. В чём другая задача? Это вы мне за то, что я поделился своим решением минус влепили? Спасибо, на хабре я уже ничего другого и не жду.
  • Каррирование функций в JavaScript
    +1
    Универсальная функция для частичного применения других функций

    простой, но не самый эффективный вариант реализации, когда-то писал свой вариант с бенчмарками относительно других реализаций: https://github.com/Riim/curry#benchmark .

  • Как работает JS: пользовательские элементы
    0
    Не видел таких, да и как такое сделаешь?
  • Вариант миграции с JQuery на чистый Javascript
    –2
    В 99% случаев больше потеряете на выросшем от таких конструкций размере бандла.
  • Вариант миграции с JQuery на чистый Javascript
    0
    Я не понимаю, о чем вы говорите.

    Про циклы говорит:


    $('.foobar').addClass('bla')

    или


    Array.from(document.getElementsByClassName("foobar")).forEach(el => {
        el.classList.add('bla');
    });
  • Когда и почему стоит использовать стрелочные функции ES6, а когда нет
    0
    стрелочные функции были придуманы в 1 очередь для работы с классами, необходимость иметь свой this в данном случае нет

    в классах такие функции лучше сразу делать методами для возможности переопределения/доопределения при наследовании.
    Например такой код:


    class Name {
        method() {
            getContacts(res => {
                this.contacts = res.data.contacts;
            });
        }
    }

    лучше сразу переписать так:


    class Name {
        method() {
            getContacts(this._handleResponse, this);
        }
    
        _handleResponse() {
            this.contacts = res.data.contacts;
        }
    }

    теперь можно переопределяя _handleResponse изменять обработку ответа не прописывая повторно код из method.

  • Настоящее и будущее безопасной работы с null и undefined в JavaScript
    0
    false, 0 и пустая строка превращаются в пустой объект

    На практика в большинстве случаев можно расчитывать, что на месте prop1 или prop2 может быть только объект, null и undefined, а prop3 уже не заменяется.


    А уж вызов метода в таком стиле выглядит еще страшнее

    я и не говорил, что решение универсальное, в каких-то случаях подходит, в каких-то нет. Скажем a?.b я бы на сегодняшний день записал как a && a.b, а вот конструкцию a.b.c.d?.e однозначно как (a.b.c.d || {}).e, вариант a.b.c.d && a.b.c.d.e при не односимвольных именах будет заметно длиннее.

  • Настоящее и будущее безопасной работы с null и undefined в JavaScript
    0
    За что минусы?
  • Настоящее и будущее безопасной работы с null и undefined в JavaScript
    –2
    ((obj.prop1 || {}).prop2 || {}).prop3
  • Maraquia — ORM для MongoDB
    0

    Реализовал не убирая await, пример:


    let user = (await User.find<User>({ name: 'Dmitry' }, ['groups']))!;
    (await user.groups)![0].printData();

    Поля передаются пока только в виде массива, позже попробую ещё в виде объектов доделать, чтобы можно было подподдокументы сразу вытаскивать.

  • Maraquia — ORM для MongoDB
    0
    Спасибо. Как я написал в статье, я фронтендер, у меня есть парочка мелких проектов где использую эту библиотеку, но говорить о production ready по ним никак нельзя. Тут мне остаётся лишь надеятся, что кто-то попробует использовать в более крупном проекте и расскажет о том, что всё хорошо или о возникших проблемах. Так что если рискнёте, то обязательно отпишитесь, даже если всё будет хорошо работать.
  • Maraquia — ORM для MongoDB
    +1

    Функции такие и в PostgreSQL есть, вопрос в том, как это на диск при изменениях пишется. Монга перезаписывает весь документ только если какое-то поле выросло в размерах. Как с этим в MySQL?

  • Maraquia — ORM для MongoDB
    0

    А что если оставлять await даже если данные сразу выкачиваются? По идее он почти не мешает, а вот если пытаться от него избавиться, то сразу возникают проблемы с типизацией, так как тип будет зависеть от аргументов в find/findAll. Прийдётся указывать что-то типа Promise<Array<User> | null> | User | null, что, конечно, будет совсем не удобно. То есть данные будут забираться сразу и оборачиваться в уже resolved промис.

  • Maraquia — ORM для MongoDB
    +1

    Есть такое, причём, насколько я понимаю, единственная причина по которой PostgreSQL нельзя назвать полноценной документоориентированной БД — это полная физическая перезапись JSONB при любых изменениях в нём.

  • Maraquia — ORM для MongoDB
    0

    Да, но +1 только для реально используемых данных. Я рассматривал ещё вариант с указанием методам find и findAll полей которые необходимо выкачать, примерно так:


    User.find<User>({ name: 'Dmitry' }, { groups: true }, m);

    тут плюс был бы в отсутствии необходимости использовать await при дальнейшем чтении таких полей, но минус в том, что не всегда заранее знаешь какие поля понадобятся и иногда приходилось бы выкачивать лишнее, да и указывать groups: true тоже не очень то хочется. В результате остановился на том, что есть.

  • Maraquia — ORM для MongoDB
    0

    Способ соединения описанный в статье скорее для тестов, более продвинутый выглядит так:


    import {
        BaseModel,
        Field,
        Maraquia,
        Model
        } from '@riim/maraquia';
    import { MongoClient } from 'mongodb';
    
    const db = (await MongoClient.connect('mongodb://localhost:27017/Test')).db('Test');
    const m = new Maraquia(db);
    
    let user = (await User.find<User>({}, m))!;
    
    user.printData();

    класс Maraquia — что-то вроде адаптера, его инстанс передаётся в методы find, findAll, save и remove последним дополнительным параметром. Передать можно один раз, он будет запомнен, то есть если он был передан в find, то позже при сохранении в save уже можно не передавать. Так же он автоматически копируется в порождаемые модели (при чтении полей соответствующих встроенным документам).


    При таком способе, во-первых, можно настроить соединение как угодно работая напрямую с драйвером mongodb, во-вторых, можно работать сразу с несколькими базами создав несколько инстансов Maraquia.

  • Maraquia — ORM для MongoDB
    0

    Да, похоже забирать данные по ссылкам Mongoose действительно умеет, про сохранение правда ничего не сказано.


    Как у Вас с этими вопросами обстоит дело (JOIN, N+1, WEHRE на полях из связанных коллекций)?

    делается дополнительный отложенный запрос при первом обращении к полю.


    Вот эта структура кажется не очень перспективной:

    в реляционных БД сохранить массив в поле не особо просто, там для хранения связи делается промежуточная таблица. Здесь тоже можно было так сделать, плюс будет в более быстром редактировании связи при большом количестве записей в ней, но будет и минус — более медленное чтение, две выборки вместо одной. Так что да, если отношение один/многие к очень-очень многим и записи в связи часто меняются, то реализованный механизм не очень подойдёт.

  • Мышление в стиле Ramda: Декларативное программирование
    +1
    > Кроме скорости разработки конкретных фич в проектах

    сильно зависит от размера проекта. Небольшие проекты действительно очень интересно делать на ФП. Небольшие до того момента пока весь проект способен уместиться в голове одного человека. Когда проект выходит за эти рамки многие восхваляемые плюсы ФП показывают свою обратную сторону. Скорость добавления новых фич остаётся примерно на том же уровне, но вот добавляется их очень мало, тк. основное время уходит на латание багов, скорость добавления которых тоже бьёт все рекорды.
  • Мышление в стиле Ramda: Декларативное программирование
    +2

    Мне стало интересно сравнить производительность приведённых примеров. Вариант на Ramda оказался примерно в 200 раз медленнее. Код:


    const Benchmark = require('benchmark');
    const { always, lt, when, __ } = require('ramda');
    
    const alwaysDrivingAge1 = age => (age <= 16 ? 16 : age);
    const alwaysDrivingAge2 = when(lt(__, 16), always(16));
    
    const suite = new Benchmark.Suite();
    
    suite
        .add('ternal 32', () => {
            alwaysDrivingAge1(32);
        })
        .add('ramda 32', () => {
            alwaysDrivingAge2(32);
        })
        .add('ternal 5', () => {
            alwaysDrivingAge1(5);
        })
        .add('ramda 5', () => {
            alwaysDrivingAge2(5);
        })
        .on('cycle', evt => {
            console.log(String(evt.target));
        })
        .run({ async: true });

    Результат:


    ternal 32 x 399,197,552 ops/sec ±1.03% (80 runs sampled)
    ramda 32 x 1,906,899 ops/sec ±1.00% (87 runs sampled)
    ternal 5 x 422,652,247 ops/sec ±1.18% (82 runs sampled)
    ramda 5 x 1,914,890 ops/sec ±1.01% (87 runs sampled)
  • Изучаем и реализуем алгоритм работы правильного observer паттерна для react компонентов
    0
    Да, что-то пошло не так и по описанной схеме лишнего вычисления действительно нет :), давненько я со всем этим разбирался и сейчас видимо так сразу не вспомню, что я там такого хитрого придумывал для лишних вычислений.
    В любом случае статья отличная, читается легко, насколько это возможно для подобного материала. Спасибо.
  • Изучаем и реализуем алгоритм работы правильного observer паттерна для react компонентов
    0
    это наверное настолько редкая ситуация что я пока не могу придумать реалистичного кейса

    со строками конечно редкая, а вот с числами и особенно с boolean вполне случается.


    то можно легко модифицировать алгоритм так чтобы не было установки флага «dirty» на зависимых ячейках сразу а происходила проверка изменилась ли ячейка уже в процессе актуализации после таймера

    вооот!) Это то, что я хотел получить! Правда я думал вы попробуете исправить реализацию в коде, а я придумаю следующий пример ломающий исправление. Ну да ладно, и так норм. Так вот, так не получится :). Во-первых, программист может захотеть прочитать зависимую ячейку до того как сработает таймер, который её "состарит" и она выдаст неактуальное значение, во-вторых, усложняем пример до четырёх ячеек:


    let a = new Cell(1);
    let b = new Cell(2);
    let c = new Cell(() => a.get() + b.get());
    let d = new Cell(() => c.get());

    а теперь меняем [a] и [b] так что бы [c] не изменился:


    a.set(2);
    b.set(1);

    дальше запускается "состаривающий" проход, он правильно состаривает [c], тк. [a] и [b] изменились и пересчитать (позже, после этого прохода) всё же нужно (алгоритм же не знает, что получится исходное значение), но как ему понять нужно ли состарить [d] не вычисляя пока [c]? А если здесь всё же вычислять [c], то это уже по сути возвращение к первой схеме реализации РП, в которой этой проблемы изначально нет.


    Я потратил довольно много времени пытаясь довести вторую реализацию хотя бы до уровня первой, в плане количества подобных фич, в результате получается либо совсем уж фичасто, либо примерно так же, но совсем уж медленно. В результате какой смысл использовать вторую схему если она минимум (в простейшем варианте с бесконечным числом фич) в 5 раз медленнее первой? В 5 Карл!!! Это не на 20% и не на 30%, это на 500% медленнее!

  • Изучаем и реализуем алгоритм работы правильного observer паттерна для react компонентов
    0
    В статье я рассматривал ситуации избегания лишних вычислений только при изменении одной ячейки

    в примере программист меняет только ячейку [a], да и зачем вообще такое ограничение? Вы вообще не рассчитываете, что программист захочет поменять сразу две ячейки? Ну и вы видимо не поняли природу этого лишнего вычисления, action из mobx здесь не причём, здесь [b] помечается как протухшая, а дальше [a] принимает исходное значение, но [b] по прежнему остался протухшим хотя очевидно, что пересчитывать его нет смысла.

  • Изучаем и реализуем алгоритм работы правильного observer паттерна для react компонентов
    0
    Ячейка label больше не будет зависеть от fullName а fullName так как от ...

    Да, верно. Это довольно легко поправить. В cellx можно подсмотреть как.


    существует тот самых "правильный" алгоритм, который ни при каких условиях и хитросплетенных зависимостях не вызовет двойного вычисления ячейки

    для обоих вариантов реализации существует далеко не один способ добиться лишних вычислений, порой это неисправимо без полной смены реализации, поэтому, если результат конечного вычисления верен, то я бы не стал называть это багом, скорее фичей. Количество таких фич, конечно, нужно сводить к минимуму, но ни для одного из вариантов у меня не удалось полностью избавиться от них. Для примера вариант лишнего вычисления для второй реализации:


    let a = new Cell(1);
    let b = new Cell(1, () => {
        console.log(123);
        return a.get();
    });
    
    b.get();
    
    a.set(5);
    a.set(1);
    
    b.get();

    console.log здесь сработает дважды, в первой реализации это полностью исправимо, во второй я в конечном счёте не нашёл такого способа (тут нужно понимать, что для конкретно приведённого выше примера исправление делается довольно легко, но дальше и пример можно легко допилить вновь сделав исправление неэффективным и тд.).

  • Изучаем и реализуем алгоритм работы правильного observer паттерна для react компонентов
    0
    > Причем, в следующий раз, когда потребуется вызвать fullName его значение будет неактуально потому что между его вызовом может сколько угодно раз обновляться lastName

    неактуальным в смысле неверным? Обновление lastName заставит обновиться и fullName, разве нет?
  • Внутреннее устройство и оптимизация бандла webpack
    0

    У вас в результате получается несколько бандлов которые грузятся на одну страницу?

  • Внутреннее устройство и оптимизация бандла webpack
    0
    Вроде как это для возможности подключения каких-либо библиотек, которые пришли в обход webpack-а

    ну да, в C подключаете D как внешнюю зависимость, а в A и B externals не используете, D попадёт в бандл пакета A|B один раз хоть используется и в C и в A|B. У меня куда более спутанные клубки и ничего два раза не грузится.

  • Внутреннее устройство и оптимизация бандла webpack
    0

    Если я правильно понял проблему, то вам сюда: externals.

  • Vibe.js — попытка сделать state management без боли
    0
    Как, например в голом mobx узнать что изменилось в транзакции и получить патч изменений

    не знаю как в mobx, у меня в cellx все изменённые в транзакции атомы попадают в releasePlan, каждый атом кроме _value имеет _fixedValue, который получит значение _value при завершении транзакции прямо перед генерацией события change, то есть прямо перед концом транзакции можно просто пройтись по releasePlan и запомнить эти два свойства. Если в mobx как-то так же, то проблем быть не должно, но если транзакции реализованы за счёт подавления вычисляемых, запоминания их и вычисления в конце транзакции, то да, вместо простейшего декоратора на 50-100 строк кода прийдётся писать хитрую библиотеку.


    В более ранних версиях cellx были также транзакции в явном виде. В них как-раз в случае ошибки используется releasePlan для отката изменений банальным переписыванием _fixedValue в _value. То есть это настоящие атомарные транзакции и в случае ошибки где-то посреди транзакции все сделанные в ней изменения полностью откатывались. Mobx, насколько я знаю, всё ещё не умеет так, по крайней мере в чистом виде, без дополнительных библиотек.

  • Vibe.js — попытка сделать state management без боли
    0
    Интересно было бы добиться такой же группировки на экшенах, с сохранением нативных классов

    декоратор action который будет заворачивать метод в транзакцию в конце которой будет делаться снимок изменений для undo/redo. Вроде легко должно реализовываться. Или я что-то забыл?

  • Vibe.js — попытка сделать state management без боли
    0

    Допустим, но вопрос зачем, так и остался открыт.

  • Vibe.js — попытка сделать state management без боли
    0

    Так зачем ещё одна библиотека? Да и разница всё же есть, для моего варианта даже без typescript будет работать автодополнение.

  • Vibe.js — попытка сделать state management без боли
    +2

    А зачем нужны отдельные секции computed, mutations? Не проще так:


    class User extends EventEmitter {
        @observable name: string;
        @observable bestFriend: User;
        @observable additionalInfo: string;
    
        @computed
        get bestFriendsName() {
            return (this.bestFriend && this.bestFriend.name) || 'No best friend :C';
        }
    
        setName(newName: string) {
            this.name = newName;
        }
    }

    ?

  • Сахарный JavaScript
    0
    много другого в ES забрали из Coffeescript

    Почему все обожатели кофе так уверены, что разработчики ES6 смотрят именно на него (кофескрипт)? По сути в кофескрипте я не увидел ничего такого чего не было во всяких питонах, руби и тд., так какого спрашивается вы всюду пихаете это чудо как что-то принципиально новое?

  • It's a (focus) Trap
    0

    Shift+Tab как-то странно работает, фокус либо переходит вперёд, как без Shift, либо (дойдя до последнего варианта) моргает и остаётся на том же месте.

  • Путешествие из Node в Crystal
    0

    Если я правильно понимаю, так сессию прийдётся хранить в редисе, нода будет создавать сессию, а в D можно будет подцеплять её, для моих задач пока хватает хранения в памяти или в куках, не хотелось бы усложнять.

  • Путешествие из Node в Crystal
    0

    Для D есть аналог Passport.js? Пока удалось найти только https://github.com/thaven/oauth, но хотелось бы стабильную версию, больше готовых провайдеров и хоть какую-то активность в репозитории.

  • Как я перестал любить Angular
    +6
    например нельзя использовать экспорты по умолчанию

    я тут с пол года назад думал про эти default и понял, что они не нужны. Import в javascript вообще спроектирован отвратительно, даже не трогая default, например, вот хочу я что-то заимпортировать из какого-то модуля, я пишу import, скобочки, и вот тут в скобочках я должен написать, что хочу, но при этом ни одна IDE мне не подскажет, что есть в модуле потому-что путь к модулю ещё просто не написан. Я должен либо наугад вспоминать, что там импортируется, либо пропускать скобочки, писать from 'путь', а дальше альтом перемещаться назад, а потом снова вперёд. Мелочь конечно, но когда она повторяется 30 раз за день, это начинает напрягать. Понятно, что можно сделать простейший сниппет решающий проблему, но всё же я считаю, что язык должен позволять полностью последовательное написание кода с автодополнением без необходимости прыгать туда-сюда. Например, в dart так:


    import 'dart:ui' show Offset, PointerDeviceKind;

    Default тоже ужасен, например, есть у меня в модуле export default class EventEmitter ..., и теперь даже если я написал путь к модулю, IDE опять же не предлагает мне EventEmitter потому-что якобы я должен придумать это имя. Но зачем? В 99.9% придуманное имя совпадает с импортируемым. В тоже время если бы default не было, то автодополнение нормально сработало бы по первым Ev (скобочки написать не проблема или добавить их в сниппет).
    Ещё часто бывает, что неочевидно был default при экспорте или нет, приходится либо пробовать методом тыка (и иногда ошибаться), либо открывать код модуля.


    В общем, я попробовал полностью отказаться от default и половина проблем исчезли, остальные добил сниппетом и парочкой плагинов для vscode. Так что, возможно, невозможность использовать экспорты по умолчанию — это плюс ангулара :)

  • Реализация, аналог и адаптация для «чистого» JavaScript'а JQuery функции JQuery(); и прилегающие к ней
    0

    У объекта читается метод xxxx, это укороченный вариант для Object.prototype.xxxx. toString у объекта особенный, он возвращает строку содержащую внутренне свойство [[Class]] объекта: http://es5.javascript.ru/x15.2.html#x15.2.4.2, в некоторых ситуациях это свойство предпочтительнее, чем результат typeof:


    ({}).toString.call([]); // => '[object Array]'
    typeof []; // => 'object'