LINUX.ORG.RU

Design patterns in C


3

3

посоветуйте, что почитать. ООП в топку.

А так же, касательно Кернигана-Ричи, посоветуйте перевод, или жестчайше необходимо в оригинале?

★★★★★

Последнее исправление: MyTrooName (всего исправлений: 2)
Ответ на: комментарий от lispfuerimmer

лолшто? Как будто ты ещё где-то в другой функции хочешь применять поинтер на освобожденную память и приравниваешь его 0 от греха подальше.

да

Весело бы смотрелся код

очень весело. только твой же параграф

где-то в другой функции хочешь применять поинтер

к этому коду не применим. в ДРУГОЙ блджад

MyTrooName ★★★★★
() автор топика
Ответ на: комментарий от lispfuerimmer

Нифига ты не помнишь. Это у тебя бинарное дерево. Лист - это через cons ячейки

Здрасти. Лисповые вложенные списки и есть бинарное дерево, притворяющееся вложенными списками. Составлено из тех самых cons-ячеек. А cons-ячейка — это пара линков, т.е. формально узел бинарного дерева.

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

anonymous
()
Ответ на: комментарий от lispfuerimmer

Это у тебя бинарное дерево. Лист - это через cons ячейки

бугага смени ник и не позорься

MyTrooName ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Если следовать концепции, они должны натягиваться на списковые структуры

Ты ничего не знаешь о CL. Я ничего не знаю про кацкель, и ничего, говорю это открыто. А у тебя лисп - это символы и листы, ну ну.

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

CL очень супирь-пупирь динамичный и позволяет определить тип каждой сущности (объекта) в рантайме. С ООП это тоже немного связано, так как тип и класс почти одинаковые вещи. В этом плане CLOS сильно привязан к языку.

Надо позвать archimag, пусть он скажет, что я нифига не понимаю, но объяснил про CL бы он лучше

lispfuerimmer
()
Ответ на: комментарий от lispfuerimmer

Ты ничего не знаешь о CL. Я ничего не знаю про кацкель, и ничего, говорю это открыто.

Ну так и я могу открыто сказать: модель исполнителя CL я не знаю. Ну сказал, и чо? :D

А у тебя лисп - это символы и листы, ну ну.

Это не у меня, дорогой, это Джона Маккарти. Будешь спорить с ним? :D

Надо позвать archimag

Это правильно, он вроде глупостей не несёт обычно. А то вот ты уже почти договорился до того, что лисп-машина не оперирует списками.

anonymous
()
Ответ на: комментарий от MyTrooName

к этому коду не применим. в ДРУГОЙ блджад

Так нахрена писать так всегда? Нахрена делать if?

lispfuerimmer
()

Gang of Four.

Но ООП обязательно нужно знать, без него в современном мире никуда. Основы функционального программирования тоже полезно. Ещё для C полезно уметь мыслить в масштабах автомата (некоторые выделяют это в отдельную парадигму, хотя я с этим не согласен).

Legioner ★★★★★
()
Ответ на: комментарий от MyTrooName

Про код - второй вариант читаемей. Не рекомендую применять оператор «запятая», он привносит путаницу в код.

или, скажем, инициализация структуры с кучей ссылок на динамические объекты: если где-то вывалился malloc() == 0, то надо все остальные освобождать. Только что наваял пару макросов, которые позволяют сделать это в 2N+1 строчек, где N - количество указателей. Но сами макросы хрен распарсишь на глаз. Вот и хочу обратиться к специалистам

Это тривиально делается с помощью goto. Примерно так:

struct foo f = {0};
f.a = malloc(..);
if (NULL == f.a)
    goto ERROR_OOM;
f.b = malloc(..);
if (NULL == f.b)
    goto ERROR_OOM;
..

ERROR_OOM:
free(f.a);
free(f.b);
..
return ERROR;
Зачем на ровном месте макросы городить?

Макросы, кстати, тоже советую не использовать по минимуму.

Legioner ★★★★★
()

Нафиг посты-то тереть... Повторю забаненому лисперу, пусть просвещается:

А вообще ты прав в некоторой степени

Я не в «некоторой степени» прав, я ябсолютно прав.

Дело в том, что на конс-ячейках можно и лист реализовать, и дерево

Лист это и есть дерево. Ну если не считать того факта, что еще и ты дуб-дерево. Слушай, я надеюсь, ты не только троллить умеешь, но и соображать, так что объясню конкретно.

Вот произвольная структура на лиспе: (a b (c 1 2) d).

Вот представление указанной структуры в виде набора cons-ячеек:

* -> * -> * -----------------> * -> nil
|    |    |                    |
a    b    * -> * -> * -> nil   d
          |    |    |
          c    1    2

А теперь ВНЕЗАПНО. Это структура, у которой в каждый нетерминальный узел входит один линк и выходит два линка — такая структура, как учит нас Кнут, называется двоичным деревом!!111

Иди матчасть учи, серьёзно. Куда тебе лиспы, начинай прямо с Кнута.

anonymous
()
Ответ на: комментарий от Legioner

Это тривиально делается с помощью goto

было уже. тривиально, но многословно

Зачем на ровном месте макросы городить?

на самом деле, хз, какое из зол меньшее

MyTrooName ★★★★★
() автор топика
Ответ на: комментарий от anonymous
#define MALLOC_FIELD(ptr) { \
    assert(!(ptr)); \
    if(!((ptr) = malloc(sizeof(*(ptr)) * wh))) { \
        printf("malloc error: Not enough memory\n"); \
        goto cleanup; \
    } \
}
    MALLOC_FIELD(material);
    MALLOC_FIELD(shape);
#undef MALLOC_FIELD
MyTrooName ★★★★★
() автор топика
Ответ на: комментарий от MyTrooName

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


some_result_t f(some_param_r p)
{
    FILE * f1 = NULL;
    FILE * f2 = NULL;
    char * s1 = NULL;
    char * s2 = NULL;
    char * s3 = NULL;

    some_result_t result = -1;

    // всякий код....

    f1 = fopen(блабла);
    if (!f1)
        goto end;

    // всякий код....

    f2 = fopen(блабла);
    if (!f2)
        goto end;

    // всякий код....

    if (!(еще какая-нибудь проверочка))
        goto end;

    // всякий код....

    s1 = malloc(блабла);
    if (!s1)
        goto end;

    // всякий код....

    if (!(и еще одна какая-нибудь проверочка))
        goto end;

    // всякий код....


    s1 = malloc(блабла);
    if (!s1)
        goto end;

    // всякий код....

    s1 = malloc(блабла);
    if (!s1)
        goto end;

    // всякий код....

    while (какой-нибудь циклик)
    {
        if (блабла)
        {
            result = чего-то там осмысленное;
            break;
        }
    }

end:
    if (f1)
        fclose(f1);
    if (f2)
        fclose(f2);
    free(s1);
    free(s2);
    free(s3);

    return result;
}
anonymous
()
Ответ на: комментарий от anonymous

Ну то есть там во втором и третьем malloc-ах должно быть s2 и s3. Криво скопипастил.

anonymous
()
Ответ на: комментарий от MyTrooName

а сегодня надоело, ищу панацею

Переходи на тёмную сторону силы: пиши на крестах.

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

anonymous
()
Ответ на: комментарий от anonymous

«кто спец? я спец?»(с)

речь не против с++ как языка-инструмента

речь против подачи с++ как ооп-онли и тем более «всё то как ооп сделанно в с++ и есть эталоное ооп»

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

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

Ну а всё-таки, как там с модульностью и динамической линковкой? А то я пока не добрался до соответствующих разделов, пишу хелловорлдики с тайпклассами.

anonymous
()
Ответ на: комментарий от anonymous

э не не не

там же «всё» проперти-листы(ака асоц массивы) - короче «1в1» обьект из того же жабоскрипта как набор имя-значение.

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

э не не не
там же «всё» проперти-листы(ака асоц массивы) - короче «1в1» обьект из того же жабоскрипта как набор имя-значение.

Это в Io так, как ты описал.

Про CL не скажу, а в лиспе именно как голой концепции - там абстрактные деревья.

Ты можешь, например, реализовать на лиспе-машине ассоциативный массив вручную как набор ((ключ значение) (ключ значение) (ключ значение) (ключ значение)). Естественно, оно будет тормозить со своим O(n).

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

anonymous
()
Ответ на: комментарий от MyTrooName

кресты для того и придумали, чтобы ты (если осилишь) не топтал попусту клавиатуру. не хочешь — жуй кактус.

anonymous
()
Ответ на: комментарий от anonymous

Пшел вон! Настоящий анон - это я.

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от anonymous

они должны натягиваться на списковые структуры

Там есть, как минимум, массив, который ты даже при очень большом желании на список не натянешь.

абстрактной лисп-машины

Абстрактная лисп-машина умеет работать с базовыми типами. Их даже в примитивной scheme (r5rs) должно быть 7 штук: числа, строки, буквы (characters), символы (symbols), массивы, списки, булевы.

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

Например, для работы базовых конструкций языка typeof, etypecase... В стандарт CL и CLOS входит в полном объёме со всемы вытекающими последствиями (можно добавить метод к любом существующему классу, любое значение принадлежит какому-то классу).

monk ★★★★★
()
Ответ на: комментарий от monk

Абстрактная лисп-машина умеет работать с базовыми типами. Их даже в примитивной scheme (r5rs) должно быть 7 штук: числа, строки, буквы (characters), символы (symbols), массивы, списки, булевы.

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

Мне в этом плане лиспы и не нравятся: что в теории там всё красиво, а на практике суровые инженерные кишки торчат отовсюду.

В качестве иного подхода можно рассмотреть, например, РЕФАЛ. В котором исполнитель умеет исполнять ровно одну операцию: паттерн матчинг. Как-то это концептуально более красиво и понятно.

anonymous
()
Ответ на: комментарий от anonymous

Мне в этом плане лиспы и не нравятся: что в теории там всё красиво, а на практике суровые инженерные кишки торчат отовсюду.

Ну не сказал бы, что инженерные. Целые числа там, не int32, а честные целые. Есть рациональные числа. У массива есть операция изменения размера. А symbol вообще к ассемблерным типам слабо относится.

В котором исполнитель умеет исполнять ровно одну операцию: паттерн матчинг

И как на нём сделать хоть что-нибудь полезное? Например корень квадратный посчитать... А то можно вспомнить ещё более концептуально красивый язык: машина Тьюринга

monk ★★★★★
()
Ответ на: комментарий от anonymous

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

Для чистой математики рекомендую на Haskell или Agda посмотреть.

monk ★★★★★
()
Ответ на: комментарий от monk

Хаскелем занимаюсь. До Agda еще не добрался. :)

anonymous
()
Ответ на: комментарий от anonymous

там встроены целые и флоаты как подмножество атомов

Ну вот, уже не одна операция. Добавилась арифметика. Думаю, если копнуть поглубже, то можно будет и аналог ссылки на переменную найти.

В лиспе тоже все не-списки являются подмножествами атомов.

monk ★★★★★
()

Подводя итог:

- читать CERT C Secure Coding Standard

- читать исходники качественного опенсорс-софта

- перейти на кресты

PS Про K&R почти ни слова, так что будем считать, что все переводы ок

MyTrooName ★★★★★
() автор топика
Последнее исправление: MyTrooName (всего исправлений: 1)
Ответ на: комментарий от MyTrooName

Эта синтаксическая акробатика с паттернами проектирования ничего общего не имеет. Если же тебя интересуют именно такие финтифлюшки, я даже не знаю, что тебе посоветовать.

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

да, слово Design в заголовке, наверное, лишнее. но Design в том числе интересны

MyTrooName ★★★★★
() автор топика
Последнее исправление: MyTrooName (всего исправлений: 1)
Ответ на: комментарий от monk

Ну вот, уже не одна операция. Добавилась арифметика.

Арифметика - частный случай паттерн матчинга. Ты можешь написать кучу правил вида:

add ничего ничего -> ничего
add ничего хреновина -> хреновина
add хреновина ничего -> хреновина
add хреновина хреновина -> большаяхреновина
.
.
.
.
add оченьоченьоченьбольшаяхреновина оченьоченьоченьбольшаяхреновина -> самаябольшаяхреновина
И получить собственную арифметику на хреновинах.

Так что на теоретическом уровне арифметику можно рассматривать просто как такую вот гигантскую таблицу паттернов.

anonymous
()

В книжном магазине купи, вот так выглядит: http://www.ozon.ru/context/detail/id/2480925/

Можно и на C++ нормально писать, но обычно пишут так что и правда хочется стереть этот мусор и переписать на чистом C.

quest ★★★★
()
Ответ на: комментарий от anonymous

тонко.

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

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

Любую логическую функцию можно представить в виде таблицы истинности.

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

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

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

Таким образом, варианты реализации могут быть различными, но семантически они все представляют собой операцию «заглянуть в таблицу».

Так что в представлении арифметических операций как набора паттернов нет ничего «тонкого», это банально. :) В данном случае реализация рефал-машины будет просто делегировать этот этап паттерн-матчинга обычному CPU, т.к. он имеет готовую логику в железе — но суть-то остаётся.

Чисто теоретически, можно, например, взять какой-нибудь набор правил трансформации, перевести его в Verilog и скомпилировать для FPGA. Получим реализацию рефал-программы в железе.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.