Обновить
16K+
49
Alex Gusev@flancer

Я кодирую, потому что я кодирую…

3,1
Рейтинг
99
Подписчики
Отправить сообщение

Мне сложно "с листа" понять, о чём этот код - мне не хватает бэкграунда. Например, PureObject , ReactiveObject - я не знаю, что это за классы. @mem - это похоже на декоратор, я тоже не знаю, что он делает. Вы показываете "верхушку айсберга" и спрашиваете, что "под водой". Я не знаю. Реактивность не находится в фокусе моих интересов, чтобы я этим заинтересовался. Я даже "чистый объект" не осилил (так и не понял, чем он отличается от "грязного"?). Почему тут наследование от PureObject , а в примере - от $mol_object? В общем, это для меня слишком сложно. Но спасибо, что предложили подумать.

Я в своей статье рассматривал "синглтон" в контексте lifestyle - сколько экземпляров одной функции порождается в процессе выполнения программы. Вот и по мнению коллеги @nin-jin функции в программах создаются в одном экземпляре (если я правильно понял его коммент выше). Паттерн ОО-проектирования "синглтон" к моим рассуждениям отношения не имеет. Но очень легко запутаться, когда два разных понятия имеют одно и то же имя.

Старгейт - не скайнет, но... а почему бы и нет?! Чем Звёздные Врата хуже Небесной Сети?

Голос Гаврилова на фоне:

Днём мы прячемся. По ночам ещё можно ходить. Только очень осторожно. У роботов-убийц инфракрасное зрение. Джон научился бороться с ними, мы их больше не боимся. Пока не начали появляться киборги. Терминаторы — это последняя модель. Самые страшные из них.

Эх, были времена, когда это было крышесносной фантастикой!!

С течением времени мы обнаружим, что являемся низшей расой

vs

Против них должна быть немедленно объявлена война на смерть

Э-э-э... "немедленная война на смерть" против "с течением времени мы обнаружим". Какие-то просто несравнимые категории!

Мы ещё не знаем, когда и что именно обнаружим, но уже готовы умереть в борьбе за. Это называется упоротость.

В любом случае приятно, что упоротость прогрессу не препятствие. Это ж с XIX века тянется!!

Вот и я о том же. ФП - это способ создания программ. Способ мышления при использовании инструмента. ООП - другой способ мышления. Отвёрткой можно забивать гвозди, а вот закручивать шурупы молотком не получится, но можно шурупы молотком забивать.

Да, я согласен, что одни инструменты лучше подходят для выполнения определённых задач, а другие хуже. Наверное, именно поэтому я, в конце-концов, программирую на JS - на нём и шурупы можно отвёрткой закручивать, и гвозди молотком забивать. На нём же, при достаточном желании и упоротости упорстве можно и шуруп отвёрткой забить. Насчёт закрутить гвоздь молотком - сильно сомневаюсь. Я б не осилил.

Что в этом коде на Си указывает на то, что он именно процедурный, и в каком месте он не соответствует функциональной парадигме?

int add(int a, int b) {
    return a + b;
}

Да, это простой пример. Это очень простой пример. И для очень простого примера должен быть очень простой ответ на мой вопрос.

Меня давным-давно учили, что процедура от функции отличается только тем, что функция возвращает результат, а процедура - нет. Но это было лет 30 назад и на Pascal'е.

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

Вот вариант для массивов от ИИ. Я на Си не думаю, поэтому не могу сказать, что там лажа, а что нет.

код для массивов от ChatGPT
#include <stdio.h>
#include <stdlib.h>

/*
 * Рекурсивная копия массива:
 * copyArray(src, n, dst, offset) копирует n элементов из src в dst,
 * начиная с dst[offset], не меняя src.
 */
void copyArray(const int *src, int n, int *dst, int offset) {
    if (n == 0) {
        return;
    }
    dst[offset] = src[0];
    copyArray(src + 1, n - 1, dst, offset + 1);
}

/*
 * insertIntoSortedArray(a, n, x) возвращает указатель на *новый* массив
 * длины n+1, куда вставлено число x в нужное место, предполагая что
 * исходный массив a (длины n) уже отсортирован. Старый массив a не меняется.
 */
int* insertIntoSortedArray(const int *a, int n, int x) {
    if (n == 0) {
        // Новый массив из одного элемента
        int *res = malloc(sizeof(int));
        res[0] = x;
        return res;
    }
    if (x < a[0]) {
        // x становится в начало нового массива, дальше копируем a
        int *res = malloc((n + 1) * sizeof(int));
        res[0] = x;
        copyArray(a, n, res, 1);  // старый массив копируется со сдвигом
        return res;
    } else {
        // Первый элемент нового массива совпадает со старым a[0],
        // а x вставляем рекурсивно в "хвост" (a+1)
        int *res = malloc((n + 1) * sizeof(int));
        res[0] = a[0];
        int *temp = insertIntoSortedArray(a + 1, n - 1, x);
        copyArray(temp, n, res, 1);
        free(temp);
        return res;
    }
}

/*
 * readSortedArray(n) считывает n чисел и возвращает указатель на
 * отсортированный массив длины n. Реализовано рекурсивно:
 * - если n==0, возвращаем NULL (пустой массив);
 * - иначе читаем одно число x, рекурсивно получаем массив из (n-1) чисел
 *   (уже отсортированный) и вставляем в него x, возвращая новый массив.
 */
int* readSortedArray(int n) {
    if (n == 0) {
        return NULL;
    }
    int x;
    scanf("%d", &x);
    // Рекурсивно получаем отсортированный массив из n-1 элементов
    int *arr = readSortedArray(n - 1);
    // Вставляем новое число x в нужное место
    int *res = insertIntoSortedArray(arr, n - 1, x);
    free(arr); // старый (короче на 1) уже не нужен
    return res;
}

/*
 * Рекурсивный вывод массива:
 * printArray(a, n) печатает n чисел массива a.
 */
void printArray(const int *a, int n) {
    if (n == 0) {
        return;
    }
    printf("%d ", a[0]);
    printArray(a + 1, n - 1);
}

int main(void) {
    int n;
    scanf("%d", &n);

    // Считываем n чисел и получаем новый (отсортированный) массив
    int *sorted = readSortedArray(n);

    // Печатаем итог
    printArray(sorted, n);
    printf("\n");

    // Не забудем освободить итоговый массив
    free(sorted);

    return 0;
}

Просто человек выше очень сильно намекает, что на С нельзя написать что-то в функциональном стиле из-за того, что "у си немного так проблемы" с неизменяемыми переменными, да "и гарантий оптимизации хвостовой рекурсии тоже нет". А ChatGPT говорит:

С теоретической точки зрения, оба языка (Haskell и C) тьюринг-полны. Это значит, что любую задачу, формально решаемую на одном языке, в принципе можно решить и на другом. Соответственно, нет «таких программ, которые можно написать на Haskell и невозможно написать на C».

Возможно, что ChatGPT неправ, а возможно, что человек выше думал написать одно, а написал другое. А возможно и я чего-то там не так понял. Например то, что он таким образом опроверг мой тезис "Бывает, что функции существуют и без замыканий. Например, в C" Я-то точно помню, лет 15-20 назад функции в С были, а замыканий не было. Если что-то за это время поменялось и теперь в Си функции без замыканий не существуют - ребята, я просто не успел за прогрессом!!

Человек выше на Си писал последний раз лет 15-20 назад. Если вам это действительно интересно, можете поговорить с ChatGPT - https://chatgpt.com/share/678c07b7-e930-800d-92c5-e92d9d800daa Он там что-то такое выдал и умно рассуждает. Можете его переубедить.

"Функции не синглтоны, потому что существуют замыкания." (с)

Мне кажется, что вы пытались донести до меня мысль "В ФП не все функции синглтоны, потому что существуют замыкания".

Вот если бы вы свою мысль оформили таким образом, я бы, возможно, и не триггернулся. А если бы автор поста не назвал его "Синглтон - корень всех зол", я бы и на статью не триггернулся. Ну, как есть.

А так-то я ни в ФП ничего не понимаю, ни в программировании на С. Высказал свою точку зрения, получил фидбек. Всё норм - это же Хабр. За этим я и здесь.

Ну так вы сами не изменяйте переменные - и все дела. ФП - это прежде всего стиль написания кода (неизменяемость данных и минимизация побочных эффектов). То, что Си не очень подходит для ФП, никак не аргументирует вашу реплику "Функции не синглтоны, потому что существуют замыкания". Функции не синглтоны не поэтому. Как говорится, "слово - не воробей, да и вообще ничего не воробей, кроме воробья" (с)

Автор оригинального поста, Maximiliano Contieri, говорит про синглтон в контексте паттернов проектирования ООП, а так-то у термина "синглтон" значений слегка больше, чем одно. Например, жизненный цикл зависимостей в DI контейнерах тоже может быть синглтоном. Поэтому утверждать "Синглтон - корень всех зол!" несколько кликбейтно. А если вам внимание важнее понимания, то вот и получите. Он про синглтон, и я про синглтон. Может у него в ООП синглтон и корень всех зол, но в ФП вообще такого понятия нет. Вернее, там все функции - одиночки. Нужны ровно в одном экземпляре.

Да. А что вас смущает?

А вот вы не правы. Бывает, что функции существуют и без замыканий. Например, в C.

Вы абсолютно правы!

Вот за что мне симпатично функциональное программирование, так это за то, что там все функции - синглтоны. Раз у них нет состояния, то на всё приложение нужна ровно одна функция, выполняющая конкретную работу. И никто её демоном не считает.

Ну и даёт Maximiliano Contieri жару в универе Буэнос-Айреса!!

Среди тех, кто верит в "светлое будущее", есть и те, которые понимают, что "Т9 на стероидах" - хороший инструмент для решения класса задач. Не AGI, конечно, но тоже ничего так. Что-то типа паровой тяги во времена гужевого транспорта. Понятно, что с лошадью и пятилетний ребёнок управляется, а на машиниста учиться нужно, но...

А Мэтт Мулленвег - знатный тролль, однако! "Новые формы лидерства", говорит...

И что мы скажем, барахтаясь в море псевдолитературы, псевдоизображений и псевдостатей о псевдооткрытиях? Ой?

Вот как раз об этом я и написал в этой статье - дискриминация интеллекта по происхождению! Какая разница, кто генерирует интеллектуальный мусор - естественный интеллект или искусственный? Если что, то весь интеллектуальный шлак, который был в интернете еще несколько лет назад, нагенерил естественный интеллект. И ничего, как-то мы шедевры в нём могли отыскать.

Толковая идея - это та, которая резонирует в интеллекте собеседника. Она не должна быть большой, красивой или свежей - она должна быть приемлемой собеседником. Любая идея в "многабукоф" - априори плохая. Она не принимается собеседником с лёту. А когда идея интеллектом собеседника приемлема, то источник её происхождения уже неважен.

Да, ИИ может генерировать километры текста. Но если попросить, то он уложит тот же смысл в 10 слов. По крайней мере, попытается. Всё-таки навыки работы с бульдозером должны отличаться от навыков работы с лопатой.

Спасибо за отличный комментарий! Без шуток. Вы очень точно изложили типовой взгляд на генеративный ИИ, как на самостоятельного актора. Именно так он и будет работать самостоятельно, без внешнего управления.

Но я бы сравнил ИИ с бульдозером. Без водителя он просто хаотично движется по поверхности и что-то куда-то перемещает, если на что-то натыкается. Ожидать от него полезных действий очень наивно, хотя он и может вдруг совершить полезную работу. Но если посадить за рычаги машины нормального бульдозериста, то их тандем по производительности на порядки перекроет человека с лопатой, даже очень умелого.

Можно ли утверждать, что яма, выкопанная человеком с лопатой, более качественная, чем яма выкопанная человеком с бульдозером? Конечно можно, если выставить соответствующие критерии - например, "точность" или "аккуратность"! А если смотреть по критерию "производительность"?

Чем текст этой статьи, созданной без помощи ИИ, лучше текста, созданного мной же при помощи ИИ? Вернее, созданного ИИ, направляемого мной? Мысль, которую я пытался донести:

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

передана точно и логично обоснованно. Уж в слова-то ИИ умеет получше меня!

Бульдозер не в ответе за ямы, которые он создаёт. За ямы отвечает бульдозерист.

Нет. Как буквы сложились, так и запостил. Даже орфографию не проверял. О чём прямо в посте честно и написал (смотрите P.P.S.)

Информация

В рейтинге
1 276-й
Откуда
Рига, Латвия, Латвия
Дата рождения
Зарегистрирован
Активность

Специализация

Фулстек разработчик
Ведущий
От 3 000 €
JavaScript
HTML
CSS
Node.js
Vue.js
Веб-разработка
Progressive Web Apps
PostgreSQL
MySQL
GitHub