juan_gandhi: (VP)
[personal profile] juan_gandhi
Что вы думаете о ковариантности и контравариантности?

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

Date: 2013-09-05 04:29 am (UTC)
From: [identity profile] spamsink.livejournal.com
Ковариантный возврат я, было дело, использовал в С++ вскоре после того, как стало можно (пишут, кстати, что это было первым расширением языка, утвержденным в 1998 году), а контравариантных параметров в С++ нет, и я не помню, чтобы чувствовал сильную потребность.

Date: 2013-09-05 11:12 am (UTC)
From: [identity profile] huzhepidarasa.livejournal.com
Тут немного о другой ковариантости речь, вроде приведения container<derived> к container<base>.

Date: 2013-09-05 04:36 am (UTC)
From: [identity profile] bytebuster463.livejournal.com
У нас тоже петиция (http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3942302-provide-covariance-contravariance-language-support) есть, хотят +'a и -'a. Как дети малые, чесслово.
Edited Date: 2013-09-05 04:38 am (UTC)

я таких слов не знаю

Date: 2013-09-05 05:26 am (UTC)
From: [identity profile] freedom_of_sea.livejournal.com
может вещь и полезная, но мне непонятно. Если даже, невероятным усилием, пойму, практическая польза непонятна, пользоваться непривычно, а теорию быстро забываю.

Re: я таких слов не знаю

Date: 2013-09-05 02:03 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
Быстро забывают только теорию, которая нахуй не нужна для работы. Соответственно, ковариантности и контравариантности не нужны.

Re: я таких слов не знаю

Date: 2013-09-06 06:00 am (UTC)
From: [identity profile] freedom_of_sea.livejournal.com
Я склоняюсь к мысли, что я просто тупой

Re: я таких слов не знаю

Date: 2013-09-06 11:14 am (UTC)
From: [identity profile] nponeccop.livejournal.com
Пока деньги получается добывать, это не страшно.

Date: 2013-09-05 06:29 am (UTC)
From: [identity profile] soloviewoff.livejournal.com
В С++ не хватает нормальной ковариантности довольно часто. Которая хотя бы через приводимость типов работала. Иначе вот это
  class Node {
  public:
    virtual Ptr<Node> parent() = 0;
    virtual Iterator<Ptr<Node> > children() = 0;
  };

  class MyNode : public Node {
  public:
    virtual Ptr<MyNode> parent() { ... }
    virtual Iterator<Ptr<MyNode> > children() { ... }
  };

уже не скомпилируется, хотя вроде все логично выглядит. Приходится либо сырые указатели возвращать, либо отдельные функции заводить в потомке. При этом приводимость и умных указателей, и итераторов через конструктор от другого типа есть.
Edited Date: 2013-09-05 06:30 am (UTC)

Date: 2013-09-05 07:48 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
это делается примерно так:

template
[Error: Irreparable invalid markup ('<typename [...] t,typename>') in entry. Owner must fix manually. Raw contents below.]

это делается примерно так:

template <typename T,typename C> class AbstractNode {
public:
typedef C children;
virtual T *parent() = 0;

virtual children begin() = 0;
virtual children end() = 0;
};

class MyNode : public AbstractNode<MyNode,vector<MyNode*>::iterator> {
private:
MyNode *_parent;
vector<MyNode*> _children;
public:
virtual MyNode *parent() { return _parent; }

children begin() { return _children.begin(); }
children end() { return _children.end(); }
};

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

Date: 2013-09-05 08:00 pm (UTC)
From: [identity profile] soloviewoff.livejournal.com
Это не совсем то. В Вашем примере нет рантайм полиморфизма относительно AbstractNode. Строго говоря, я здесь смысла в виртуальности функций в AbstractNode не вижу. Допустим, будет еще MyNode2 - как написать код, который имеет дело общим образом с MyNode и MyNode2 через AbstractNode?

Date: 2013-09-05 08:27 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
про рантайм полиморфизм - обычное наследование. а если хочется контрвариантности, то "С++ делегаты"(в гугле). реализовано в куче библиотек, уже изучены вдоль и поперёк все плюсы и минусы.
но на практике это не нужно. с детства пишу на С и С++, делала гигантские проекты федерального уровня. но вот наследование и всякие такие извраты практически не пригождаются. это так, для институтов.
Edited Date: 2013-09-05 08:28 pm (UTC)

Date: 2013-09-05 08:49 pm (UTC)
From: [identity profile] soloviewoff.livejournal.com
Контрвариантности редко хотелось, а нормальной ковариантности чаще, о чем и ответил автору оригинального вопроса.

Date: 2013-09-05 09:36 am (UTC)
From: [identity profile] mikkim08.livejournal.com
Я бы сказал, что ковариантность и контравариантность -- вещь понятная простом человеку. Я и сам ее вроде понял и другим научился об'яснять, что это такое, и зачем она нужна.

Date: 2013-09-05 01:01 pm (UTC)
From: [identity profile] migmit.livejournal.com
Позавчера объяснял студентам, что в некоторых случаях Hom становится таки ковариантным по первому аргументу.

А вообще, конечно, нужны.

Date: 2013-09-05 02:13 pm (UTC)
From: [identity profile] hill-report.livejournal.com
только что замутил монаду в плюсах, почти парсер-комбинатор только не над буквами,
а над коллекцией объектов

Date: 2013-09-05 06:08 pm (UTC)
From: [identity profile] timgabets.livejournal.com
Ну, для меня и джава - мусорка. Существует только Си.

Date: 2013-09-05 08:06 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
я вот тоже думаю: кернел написан на С, а что ещё нужно? всё остальное - лишь рябь на поверхности кернела.
жабу я когда-то давно смотрела. не понравилось: слишком мало свободы, слишком много информации, которую надо держать в голове.

Date: 2013-09-11 10:58 am (UTC)
From: [personal profile] alll
Нужно уметь несколькими словами выражать то, что сейчас занимает несколько фраз. Причём без потери читаемости и устойчивости к ошибкам (а желательно и с улучшением). C/C++ в этом смысле не особо лучше макроассемблера, местами возможно даже и хуже.

Date: 2013-09-11 12:23 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
смотря что писать. у нас вот машины работают на огромных скоростях. я не имею права жрать даже один процент процессора. да и под микроконироллеры пишут на С. С универсален. остальное - частные решения. кого интересует количество кода, когда вопрос только в скорости выполнения?
а ошибки - они не в языке, они в программистах :) да,в С нет защиты от дурака. предполагается, что дурака не пустят писать ответственный код.

и, кстати, нет ничего плохого в ассемблерах. иногда особо важные куски кода нужно написать на ассемблере. или бывают ошибки в компиляторах и надо не только уметь понять, где в скомпилированном коде ошибка, но и исправить её.
Edited Date: 2013-09-11 12:25 pm (UTC)

Date: 2013-09-11 12:46 pm (UTC)
From: [personal profile] alll
> у нас вот машины работают на огромных скоростях

Масштабирование же. Для обработки статыщ запросов в секунду можно взять одну супермашину или стотыщ говномашин. Один чорт затык будет не в вашем коде, а в DBMS.

> да и под микроконироллеры пишут на С

Под микроконтроллеры - да ради бога, там не то количество кода, чтобы переживать из-за [не]выразительности средств.

> в С нет защиты от дурака. предполагается, что дурака не пустят писать ответственный код

А между тем регулярно пускают, судя по поведению иных драйверов. Да и дело не том, дурак пишет или нет. От ошибок никто не застрахован.

> нет ничего плохого в ассемблерах

Так-таки и "ничего"? Даже на солнце бывают пятна.

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

пить можно всем! знать нужно только когда и где, и с кем, и сколько

Лучше однако, чтобы это были очень небольшие куски и достаточно хорошо изолированные.

Date: 2013-09-11 01:24 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
у нас "машины" - это промышленная автоматизация. и масштабирование там не канает: габариты, требования к ТУ и т.д. базы там только на верхнем уровне, по сути, они не используются при работе. только для загрузки параметров и формирования отчётов для юзеров.

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

Edited Date: 2013-09-11 01:28 pm (UTC)
(deleted comment)

Date: 2013-09-05 07:58 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
аналогично. пишу подобную лабуду на вопросы студентов на форумах. студенты впадают в оргазм. но в реальной жизни такое нафиг не нужно, как показывает практика. реальная жизнь требует мобильности, и быстрой подстройки под сменившиеся требования. и тогда все теории идут к чертям. а наворотивших их припирают к стенке с вопросом: ну и нах было выпендриваться? недавно пришлось переписывать код одного любителя теории (студень после выпуска перевозбудился и насовал в простейшую софтину многочисленные классы с наследованием и дженериками). пришлось всё выкинуть и написать заново, через обычные массивы. быстрее и эффективнее в тыщу раз получилось :) а главное - код стал читабельным!

Date: 2013-09-05 09:38 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
Это прямо какая-то параллельная вселенная! :)

Я думаю, с *вариантностью не сталкиваются те, кто полиморфных функций не писывали.

Простейший пример. Читаем хип дамп. Указатели могут быть либо все 32-битные, либо все 64-битные. Ваши варианты решения на Си? Может, я тупой, но здесь полиморфизм налицо. Цепляем экзистенциональный квантификатор и пишем, как буд-то у нас один тип указателей. Теперь пишем функции, работающие с хип дампом. Опять полиморфизм. Результаты *вариантны размеру указателей.


Ещё пример? ок. Вот мап-редюс. Он не умеет параллелизовать деревья. Но умеет параллелизовать свёртку любого моноида. Но тут же сплошной функтор и монада. А вы на каждый пук свой параллелизм пишете?


А о посете событий вы в Си каким образом рассуждаете? Или у вас всегда один толстый лок на всё? Но это уже не о *вариантности как таковой, а что "си - это всё"

Date: 2013-09-05 09:43 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
полиморфизм в такой примитивной задаче сожрёт весь проц. вообще-то, указатели в системе всегда либо 32 либо 64. но динамическое распределение памяти и смещения никто не отменял пока что. какой ещё полиморфизм??? обычный массив! динамически выделили, поработали, освободили память.

Date: 2013-09-05 09:55 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
нюню.

про массив понятно, а дальше? Хип дамп - он снят на одной машине, а смотрим на другой. Как вы собрались привязываться к размеру указателя в системе? Найти цепочку от GC Root до объектов, удовлетворяющих предикату, в этом массиве байт. По идее вы должны объяснить один простой вопрос:

а. вы везде будете делать проверку "у нас 32 или 64 бита указатель?", когда указатель из хипа прочитать нужно?

б. вы будете по две функции на каждый размер делать?

в. всё-таки напишете полиморфную функцию вида (forall a. IdSize a => Heap a -> ResultSet (Value a)

Date: 2013-09-05 10:20 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
в венде, например, на другой машине вы дамп не посмотрите. факт из жизни. но даже если это другая система и это возможно: битность целевой машины известна, что мешает обращаться по смещениям? я вообще не понимаю, в чём проблема.
я не буду делать функции. я сделаю ptr+=size. size - известен.

параллелизм осуществляется системой, если программист явно не задал использование ядра потоком. чем прямее метод - тем он быстрее. и локов в программе могут быть тысячи. кто мешает-то? "большой и жирный" - это ваши фантазии.
Edited Date: 2013-09-05 10:21 pm (UTC)

Date: 2013-09-05 10:24 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
"я сделаю ptr+=size. size - известен. "

size известен. Далее, вы как будете (int32)(ptr+size) и (int64)(ptr+size) в зависимости от size?


"параллелизм осуществляется системой"

я ж и говорю, параллельная вселенная какая-то.

Date: 2013-09-05 10:28 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
она не параллельная. я, увы, системный программист. и отлично знаю реализации параллельности под вендой и под линюксом. система занимается распределением параллельности сама. максимум, чем занимается юзер явно - это синхронизация потоков. но вы, как я вижу, разницы между синхронизацией потоков (процессов) и параллельностью не видите вообще, ибо чистый прикладник. так вот: она есть!
охтытетить, какой студень упёртый! size один раз инициализируется, при старте. и всё. можете в регистровую переменную его засунуть (впрочем, компилятор и так это сделает, если в этом будет необходимость при частых обращениях). и не надо никаких проверок. адресация в дампе не меняется, от начала до его конца.

Date: 2013-09-05 10:30 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
:) да с адресацией уже понятно, вопрос то не в этом был, а теперь вы же должны прочитать то ли 4, то ли 8 байт.

Date: 2013-09-05 10:32 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
это уже известно. потому что мы дамп не с потолка взяли. и ещё раз: size - известен. в чём проблема? если вам так уж нравятся лишние функции - передайте указатель. и читайте оттуда size байтов. всё.

Date: 2013-09-05 10:36 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
какие-то ответы совсем не в строку. size байт прочитать - понятно, понятно! понятно?

вы в какую переменную его засунете - в int32 или int64? вы же где-то объявите переменную, которая с этим значением что-то сделает - скажем, поищет что-нибудь в таблице.

Date: 2013-09-05 10:46 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
да вот вам встряла эта переменная! оперируйте указателями - и не будет головняков. а конечная функция из глобальной переменной (или откуда угодно) возьмёт этот size и прочитает нужные ей байты. тут не принципиально, можно взять int64, от этого ничего не изменится.
Edited Date: 2013-09-05 10:47 pm (UTC)

Date: 2013-09-06 07:10 am (UTC)
From: [identity profile] sassa-nf.livejournal.com
а, ну, так вот, вы все указатели таким образом приводите к int64 (раз указатель на указатель "можно взять" int64) и ваш мемори футпринт будет 2х больше нужного.

Date: 2013-09-05 10:33 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
"максимум, чем занимается юзер явно - это синхронизация потоков."

:)

Date: 2013-09-05 10:35 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
ну, для меня программист верхнего уровня - это юзер. потому что я обычно пишу дрова и прошивки. поэтому чаще для меня программист - это юзер.

Date: 2013-09-05 10:40 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
нутк, вот и масштаб задач стал ясен.

Date: 2013-09-05 11:08 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
ну какбэ до этого я писала систему обмена данными Сбербанка и Таможни :)
масштаб задачи был - на всю страну. сотни тысяч серверов под разными осями должны были работать с софтиной. причём быстро и без сбоев.
так что с масштабами у меня всё в порядке. я ещё и кроссплатформой много занимаюсь.

я все навороты С++, вплоть до С++11 и его реализации на разных копиляторах, знаю лучше любого студента и даже преподавателя. но! я понимаю, что этим лучше не злоупотреблять. лучше не усложнять вещи там, где этого не требуется.
да и, пожалуй, я с трудом могу представить себе задачу, где бы потребовалась перегрузка и виртуальность и она была бы оправдана. это какие-то слишком абстрактные задачи, с которыми на практике я лично не сталкиваюсь.

Date: 2013-09-06 12:15 am (UTC)
From: [identity profile] yatur.livejournal.com
Круто. А чем Сбербанк обменивается с таможней? Информацией о платежах?

Date: 2013-09-06 12:20 am (UTC)
From: [identity profile] iron-bug.livejournal.com
отдельные системы, одна - для Сбера, другая - для таможни.
у Сбера - платежи, у таможни - свои документы. просто эти системы одна компания делала. там был целый комплекс софтин для тех и для других.

Date: 2013-09-06 07:26 am (UTC)
From: [identity profile] sassa-nf.livejournal.com
Я отнюдь не сомневаюсь в ваших способностях. Я лишь говорю, что масштаб другой. У вас задача прочитать что угодно откуда придётся. У меня задача не прочитать что попало откуда ни попадя.

123К запросов в секунду, время отклика 1.116 мс, нагрузка 24 ядер процессора 67%. Это значит, что мы используем 0.67*24=16.08 секунд процессорного времени в каждую секунду. Стало быть, на каждый запрос уходит ровно 16.08/123000=130.7 микросекунд процессорного времени с учётом Garbage Collection и прочего оверхеда. Если это всё переписать на волшебный язык Си настолько чудесным образом, что 130 микросекунд превратится в 0 (ноль), у меня время отклика изменится всего на 11.7%. Но ведь процессорное время не будет нулём.

Ок, напишете так, что будет работать в целых два раза быстрее. Это всего 5% разницы во времени отклика (соответственно и пропускная способность для фиксированного количества пользователей). И ради этого мучиться с pointer arithmetic и зажимать себя в рамки Сишного менталитета?

Тем же токеном можно эту систему переписать на скалу и разница в производительности будет доли процентов. Зачем тогда себя мучить недоделанной системой типов?

Date: 2013-09-05 10:24 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
нет, не напишу я никакую функцию. и уж тем более полиморфную. потому что это будет в тысячи раз медленнее и нафиг это надо, когда есть линейный массив и чтение этого линейного массива через указатель. смещения известны. только указатель и оператор +. всё. больше ничего не нужно.

Date: 2013-09-05 11:05 pm (UTC)
From: [identity profile] yatur.livejournal.com
void* ptr = malloc(len * (bits >> 3));

Вот такая суровая сишная ковариантность :)

Date: 2013-09-05 11:15 pm (UTC)
From: [identity profile] iron-bug.livejournal.com
а зачем ковариантность там, где просто массив байтов? а суровая сишная реализация в тысячи раз быстрее :)
да и никакая она не суровая, на самом деле. куда там до суровости! примитивные операции обработки данных.

Date: 2013-09-05 11:39 pm (UTC)
From: [identity profile] yatur.livejournal.com
Достаточно суровая. Скажем, если мы делаем

FILE* f = fopen("dump.txt", "rb");
size_t size = items_in_dump * (item_bits>>3);
void* ptr = malloc(size);
fread(ptr, 1, size, f);

то может очень неудобно получиться, если CHAR_BIT != 8.

Потому что у нормальных людей байты - это байты, а у сишников байты - это черт знает что. Я лично работал с компилятором, где CHAR_BIT было равно 32. Что-то на SunOS, если я не ошибаюсь. Зато очень быстро :)

Date: 2013-09-06 07:33 am (UTC)
From: [identity profile] sassa-nf.livejournal.com
здесь ещё фокус, что items_in_dump - это не исключительно указатели. я эти подробности и не вспоминаю, т.к. не в них дело.

Date: 2013-09-05 11:02 pm (UTC)
From: [identity profile] yatur.livejournal.com
Ну, это как с любым неявным преобразованием. Иногда думаешь - о, круто, а иногда - какая сволочь это придумала? Ну а по большей части оно проходит незаметно. Мало кто, увидев object obj = new FooBar(); начинает глубоко задумываться о теории типов - вот и тут так же.

Date: 2013-09-06 07:03 am (UTC)
From: [identity profile] exceeder.livejournal.com
Концепция простая. Чтобы поменьше ошибок в коде было, понять полезно. Осваивание основ происходит методом проб и ошибок чуть ли не сразу при виде каких-нибудь дженериков (ака обобщенных типов) и попытка написать свое. Чаще всего без последствий для мозга и "лишь бы уже этот код сдать без видимых багов"

В жизни - от задачи зависит. Если сталкиваешься вообще с этим, то уже точно это некий универсальный код. Скажем, вот недавно нужно было расширить и сделать более удобным использование GWT DataGrid (ну то есть обычная табличка данных с перелистыванием по страницам в вебе написанная на Джаве). Задача абстрактная, дженерики везде, а дальше там уже недалеко и до которая как бы подразумевает ковариантность в море инвариантности... Ну и че - код универсальный, значит сдавать каждой группе, которой придется пользоваться, сразу с заточенным на них примером ("А вот так можно описать базовый и вот это надо доимплементировать для каждого из ваших специфических гридов")

Так я к чему. На примере грида - я не придумал красивого решения (это не значит, то его нет, конечно). Сделал инвариантным. Одни удобнее контраварианто делать, другим - коварианто. Зависит сильно от модели данных и решаемой задачи.

Profile

juan_gandhi: (Default)
Juan-Carlos Gandhi

June 2025

S M T W T F S
1 2345 6 7
8 9 10 11 121314
15161718192021
22232425262728
2930     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 15th, 2025 02:00 pm
Powered by Dreamwidth Studios