LINUX.ORG.RU
ФорумTalks

Cудьба Mono


0

5

Мигель перешел в стан врага и вещает о «мертвом мертвейшем линуксе».

Mono for Android - минимум 300$. Mono for iOS - минимум 300$. С леденящим душу страхом жду Mono for Lin/Win/Mac - минимум 300$ :)

Моно на линуксе рип-рип? Или все это ерунда, всё будет хорошо и замечательно?

Перемещено mono из development

★★★★☆

Ответ на: комментарий от drBatty

Причины по которым ты не сможешь реализовать сборщик мусора (отличный от консервативного) я тебе уже указал.

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

Можно сделать несложный сборщик, но для этого придётся отказаться от: 1) экономии ресурсов (в управляемых языках с этим лучше); 2) ряда возможностей си++, включая указатели и new.

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

Я подразумевал реализацию под С++ без урезания возможностей.

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

Я сохранил адрес объекта в переменную. Как сборщик мусора будет различать int с данными от int c указателями?

ты споришь со мной за C++, но при этом аргументация у тебя в стиле C. Оператор new в C++ тебе выдаст _объект_, а никакой не адрес. А этот объект в состоянии запомнить, на кого он «указывает», на данные, или ещё на что. Если тебе это конечно надо. Компилятор тебе просто не позволит преобразовать твой «указатель» скажем в int, если ты конечно явно не пропишешь оператор преобразования (что очень удобно, например для адресации 38го элемента коллекции. В каком смысле он «38й» - решать исключительно тебе)

В консервативном сборщике он тупо просматривает все выровненные данные и если значение попадает в диапазон допустимых адресов, сборщик считает объект достижимым. Он не может отличить число от указателя. Поэтому в консервативном сборщике невозможно перемещение объектов используемое в stop-n-copy алгоритме.

ну и что?

Ты ничего не знаешь о сборщиках мусора. В нормальных gc мертвые объекты не трогаются вообще, на скорость влияет только количество живых объектов.

пока памяти немеренно они действительно не трогаются. Но если ты засрал всю выделенную тебе память, сборщик просто вынужден будет перед выделением памяти выяснить, какой объект действительно мёртвый, а какой ещё жив. В упомянутой тобой примитивной схеме, которой уже лет 50, сборщик тупо копирует живые объекты во вторую область памяти. Эта стратегия довольно просто реализуется на C++, путём перезагрузки оператора new, который и будет этим заниматься при необходимости. Это делается в базовом классе, от которого наследуются все классы, которые нуждаются в таком gc. Живость объектов можно реализовать по разному, например подсчётом ссылок на объект. Ссылки будут увеличивать operator=() для такого «указателя», т.о. мы всегда будем знать, сколько «указателей» ссылается на наш объект. Очевидно, есть смысл запретить создавать объекты напрямую, минуя наш «указатель», для этого нужно например сделать конструкторы его private. Тогда кодеры никак не смогут манипулировать нашими объектами напрямую, а только лишь посредством наших «указателей».

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

ООП вообще нет и быть не может операции «равно»

без перезагрузки operator=() никакого gc у нас не получится.

Жж0ш напалмом.

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

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

я ждал сего глубокомысленного замечания, потому нагуглил для тебя 877 примеров допустимого кода на сишарпе: http://govnokod.ru/csharp

сборщик (и любой другой код) НЕ обязан учитывать говнокод, который приводит к UB. Твой пример некорректен, вне зависимости от (не)использования gc.

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

Видно, я что-то упустил из последних лет развития Си++. Можешь дать пример кода, где из new возвращается не указатель?

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

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

не «как», а «кто». Менеджер проекта, который объяснит, что всё это уже придумали за тебя давным-давно люди, гораздо более прошаренные и в том и в другом.

ага. И заставит юзать сишарп? Это пожалуй единственная здравая мотивация в пользу сабжа и самого сишарпа. Впрочем сабж всё равно не нужен, ибо в таком случае я поставлю нормальную Windows.

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

lol, я тоже об этом подумал. Но учитывая некоторые нюансы Scala, так и есть

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

Если это и сборщик мусора, правильнее назвать его не «простым», а «вырожденным».

угу. Это никак не отменяет того факта, что он мне сэкономил уйму времени. По ТЗ объекты таки иногда уничтожаются, и это надо было тоже учесть. Если-бы я использовал обычную дефолтную стратегию, я потерял-бы кучу времени и сил, и в рантайме, и при разработке, ибо дефолтная стратегия совсем не учитывает такой случай. Схема Бейкера ещё хуже в данном случае...

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

ты споришь со мной за C++, но при этом аргументация у тебя в стиле C. Оператор new в C++ тебе выдаст _объект_, а никакой не адрес. А этот объект в состоянии запомнить, на кого он «указывает», на данные, или ещё на что. Если тебе это конечно надо. Компилятор тебе просто не позволит преобразовать твой «указатель» скажем в int, если ты конечно явно не пропишешь оператор преобразования (что очень удобно, например для адресации 38го элемента коллекции. В каком смысле он «38й» - решать исключительно тебе)

Я тебе привел пример компилируемого валидного С++ кода. Как ты будешь реализовывать stop-n-copy сборщик в таком случае?

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

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

Это делается в базовом классе, от которого наследуются все классы, которые нуждаются в таком gc. Живость объектов можно реализовать по разному, например подсчётом ссылок на объект. Ссылки будут увеличивать operator=() для такого «указателя», т.о. мы всегда будем знать, сколько «указателей» ссылается на наш объект.

Классная стратегия. Как будешь решать проблему циклических ссылок? Как такая стратегия ударит по производительности в многопоточном окружении, объяснять надо?

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

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

Что тебе нужно, имя директории?

ага. Не очень понятно, где именно хранится кеш? В /tmp/ которую юзер засунул в память? Или в $HOME, которую юзер справедиво считатет своей, и его напрягает, что там храняться какие-то хеши? (некоторые юзеры хранят в $HOME исключительно свои настройки, и ничего более. Документы и прочее хранятся на специальных разделах, возможно удалённо, или даже распределёно)

Впрочем, в вашей венде всё хранится в одном большом помойном баке...

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

Причины по которым ты не сможешь реализовать сборщик мусора (отличный от консервативного) я тебе уже указал.

не указал. Если объект невозможно создать иначе, чем через наш «указатель», то объектом также и невозможно будет и манипулировать иначе, чем через наш «указатель». Таким образом объект никак не сможет выйти из нашего периметра. Что в этой схеме тебе не понятно?

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

ты не понял

Так уж ты объясняешь.

я предлагаю возвращать указатель на специальный объект

т.е. new Foo() возвращает не Foo *, а FooPtr *? Не подходит, ибо на указателе нельзя перегрузить operator->. Т.е.

Foo *f = new Foo();
f->m(); // так нельзя - используется обычный operator->

Нужно примерно так:

Foo *f = new Foo(); // мапит память и запоминает указатель в глобальной таблице

f->m();

delete foo; // убирает указатель из глобальной таблицы и анмапит память
tailgunner ★★★★★
()
Ответ на: комментарий от drBatty

я ждал сего глубокомысленного замечания, потому нагуглил для тебя 877 примеров допустимого кода на сишарпе: http://govnokod.ru/csharp

Как этот код влияет на работоспособность шарпового gc?

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

Схема Бейкера ещё хуже в данном случае...

Схема Бейкера рассчитана на долгоживущие программы, которые постоянно создают и уничтожают объекты. Твоя программа явно не такая.

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

не указал. Если объект невозможно создать иначе, чем через наш «указатель», то объектом также и невозможно будет и манипулировать иначе, чем через наш «указатель». Таким образом объект никак не сможет выйти из нашего периметра. Что в этой схеме тебе не понятно?

C++ позволяет создать объект не через твой «указатель».

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

Можно сделать несложный сборщик, но для этого придётся отказаться от: 1) экономии ресурсов (в управляемых языках с этим лучше); 2) ряда возможностей си++, включая указатели и new.

1) где и как будут тратится ресурсы? Переменные в ЯП вроде C# как раз и образуют «умный указатель» в стиле C++.

2) объект может быть практически не отличим от указателя благодаря operator=(), operator->() и прочим вроде operator[](). Всё это является синтаксическим сахаром, и с лёгкостью выкидывается компилятором. Но в C++ коде такой объект смотрится как самый обычный указатель.

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

Переменные в ЯП вроде C# как раз и образуют «умный указатель» в стиле C++.

Ыыыы... короче, мужик, ты зациклен на Си++, это плохо. За пределами Си++ есть очень много всего, а ты зачем-то сидишь в камере. Выйди погуляй, снаружи тоже интересно %)

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

Похоже на намеренный отстрел яиц. Лучше бы сразу на 0 поделил

+1

а потом можно порассуждать, о том, какие хреновые CPU делает Intel (или AMD, зависит от религиозных предпочтений аффтора).

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

(не по теме сообщения, ответом на которое является этот коммент)

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

Мы вот тоже на жаве имеем метапрограммирование, функциональщину, множественное наследование и прямое управление памятью путем эмуляции всей это херни (или в твоей терминологии «сделали это сами»), но это ведь не повод утверждать, что полученное — это Java. Это какой-то метаязык, исходный код на котором находится исключительно в наших головах, а потом руками транслируется в код на жаве. Другой язык, не сама Жава. Иногда мы формализуем этот язык, получается DSL, для которого пишем на жаве интерпретатор или компилятор — и тогда уже даже внешний наблюдатель сможет понять, что это нифига не жава. Идея, мысль, алгоритм - они должны напрямую выражаться в терминах языка. Это когда ты хочешь отфильтровать коллекцию и пишешь «collection.sort», вместо написания эмуляции путем использования цикла. Это когда ты хочешь отнаследовать объект А от Бэ и пишешь «A extends Бэ», а не склеиваешь структуры-таблицы виртуальных функций с ручным разрешением конфликтов.

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

ООП вообще нет и быть не может операции «равно»
без перезагрузки operator=() никакого gc у нас не получится.

не путай операцию, и operator=()

Я их уж 20 лет как перестал путать %) А ты объяснишь, какое отношение имеет operator= к сборке мусора, и почему операции «равно» в ООП нет и не может быть? Питон с тобой не согласен.

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

Ыыыы... короче, мужик, ты зациклен на Си++, это плохо. За пределами Си++ есть очень много всего, а ты зачем-то сидишь в камере. Выйди погуляй, снаружи тоже интересно %)

приходится иногда. Интересно конечно, вот только непонятно. Особенно мне нравятся НЁХ вроде массивов в пыхе - лично я до сих пор не понял, что это собственно такое на самом деле. За то использовать их можно как любую структуру данных - был массив целых - добавил элемент a[«xxx»] - ВНЕЗАПНО это стало ассоциативным. А может стать очередью или там стеком...

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

Переменные в ЯП вроде C# как раз и образуют «умный указатель» в стиле C++.

Ловите наркомана.

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

Интересно конечно, вот только непонятно. Особенно мне нравятся НЁХ вроде массивов в пыхе

Пых интересен с психологической и исторической точек зрения - как и почему на свет появляются говноязыки, почему их используют, как они эволюционируют. Но есть и технически интересные языки - от *ML до Scala.

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

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

кажется ты ещё не понял, что с таким подходом как ты предлагаешь, можно сравнивать что угодно с чем угодно, но только НЕ C++. Ибо в C++ по умолчанию нет НИЧЕГО. Встроенные фичи (даже если они есть) максимально простые и тривиальные. Такие как оператор копирования (который тупо переносит содержимое), или оператор new (который не менее тупо вызывает malloc() или что там в текущей системе за неё).

Мы вот тоже на жаве имеем метапрограммирование, функциональщину, множественное наследование и прямое управление памятью путем эмуляции всей это херни (или в твоей терминологии «сделали это сами»), но это ведь не повод утверждать, что полученное — это Java. Это какой-то метаязык, исходный код на котором находится исключительно в наших головах, а потом руками транслируется в код на жаве. Другой язык, не сама Жава.

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

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

именно. Потому в C++ нет, не было, и не будет никакого sort(). Но ты можешь заюзать STL, можешь заюзать ещё что-то, или даже сделать свой sort().

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

Я их уж 20 лет как перестал путать %) А ты объяснишь, какое отношение имеет operator= к сборке мусора

когда ты пишешь x = y, объект y выходит за пределы периметра, и мы теряем над ним контроль. И потому не можем отличить нужный объект от мусора.

Если нам нужна сборка мусора, то нам нужен особая операция =, которая не только копирует объект, но и сохраняет инфу о том, что у этого объекта получилась копия. И если уничтожается x, то сборщик мусора не будет уничтожать этот объект, т.к. знает, что есть копия y. А если копий нет, то можно и уничтожить объект, на который не ссылается ни одна переменная.

и почему операции «равно» в ООП нет и не может быть? Питон с тобой не согласен.

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

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

Ибо в C++ по умолчанию нет НИЧЕГО

Кроме 500 страниц спеков, описывающих всякие извращения с оператором присваивания. Что такое ООП? Наличие ключевого слова class?

Будь C++ нормальным языком, в нём не было бы возможности переопределить оператор присваивания. Потому что этот оператор должен действовать единственным образом — скопировать структуру данных справа налево. Если это объект, так пусть просто скопирует все поля этого объекта. Если среди них есть какие-нибудь указатели и хочется скопировать не указатели, а данные по ним, то пусть программист определяет у класса метод Copy(), который будет явно вызываться.

И будет две различных операции, каждая для своей цели. a = b ≠ a = b.Copy()

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

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

Если справа атомарный тип, он копируется. Если справа объект, то копируется ссылка на него. Вот и всё.

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

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

Переменные в ЯП вроде C# как раз и образуют «умный указатель» в стиле C++.

Нет, это обычные (тэгированные?) указатели. gc может их обойти, т. к. в стеке ничего левого не лежит (а если и лежит, то среда об этом знает), так что никаких накладных расходов до запуска gc нет. В стеке си++ может лежать всё что угодно, и нужно как-то отслеживать именно ссылки на объекты в куче. На это будут расходы и памяти, и времени.

объект может быть практически не отличим от указателя благодаря

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

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

Отлично объяснил, почему С++ больше не нужен ж)

Байткод -> Ассемблеры -> Макроязыки (с ассемблерными вставками) -> Процедурные и прочие языки начала второго поколения (со вставками макросов и ассемблеров) -> Переходные объектно-ориентированные и функциональные языки (со вставками на процедурщине) -> Развитые ооп и фн языки (прямая поддержка рефлексии/интроспекции, прямая поддержка DSL и кодогенерации, contextual keywords, contextual code, etc) -> Декларативные языки с управляющими вставками

Твой С++ — остался где-то там в прошлом, в переходе от машинного кода к чему-то что может херачить человек. Отличный язык, года для 90-ого, все еще хороший для 98-ого. Погляди-ка на календарь, сейчас 2012. Сейчас даже пролог уже устарел. Через десять лет станет 2022, а еще через пару десятков лет мы будем старичками, а люди будут смеяться от одной мысли о ручном управлении написанием кода.

В С++ нету sort. В нем нету вообще ничего, что сейчас нужно. Поэтому он и не нужен //кэп

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

Если нам нужна сборка мусора, то нам нужен особая операция =, которая не только копирует объект, но и сохраняет инфу о том, что у этого объекта получилась копия.

Для консервативного сборщика, единственно возможного в Си/Си++, ничего подобного не нужно. Для не-консервативного... думаю, тоже не обязательно.

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

Вообще-то это именно простое копирование, поверь старому Питон-прогеру. Но вопрос был не о копировании, а об операции сравнения:

drBatty> в ООП вообще нет и быть не может операции «равно»

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

бросай программирование - оно не для тебя

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

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

остался где-то там в прошлом

конечно, сейчас рулят ведь не C/Obj-C/C++, а Java и C#, правда рулят они как-то странно

В С++ нету sort

вот так новость

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

C рулит там, где его ниша — программирование всяких низкоуровневых вещей. Obj-C рулит на айфонах и только, да и то в последнее время использования этой какашки можно избегать и там.

А С++… популярен примерно по той же причине, что и пхп в вебе.

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

Это обычная практика в языке Go

это имеет смысл только в том случае, если Copy() вернет ссылку, и a будет просто ссылаться на новую копию, иначе будет оверхед на ровном месте, если уж и делать такой метод, то только b.Copy( a )

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

А С++… популярен примерно по той же причине, что и пхп в вебе.

конечно, всякие компиляторы, кады, фотошопы, топовые игры, браузеры и их движки, СУБД и пр. - обычные поделки

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

А С++… популярен примерно по той же причине, что и пхп в вебе.

конечно

А это и правда так %) На тот момент просто не было ничего лучше и скромнее по ресурсам.

всякие компиляторы, кады, фотошопы, топовые игры, браузеры и их движки, СУБД

Почти все «компиляторы, кады, фотошопы и браузеры» начали писаться 20 лет назад (или больше). А топовые игры - ниша относительно небольшая, да и там уже не чистый Си++.

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

На тот момент просто не было ничего лучше и скромнее по ресурсам.

лучше ЯП точно были, это любой анонимус с ЛОРа подтвердит ) а насчет «скромнее по ресурсам» - ничего не поменялось

Почти все «компиляторы, кады, фотошопы и браузеры» начали писаться 20 лет назад (или больше)

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

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

насчет «скромнее по ресурсам» - ничего не поменялось

Да неужели? Сейчас за те же деньги можно купить на порядки больше ресурсов.

Почти все «компиляторы, кады, фотошопы и браузеры» начали писаться 20 лет назад (или больше)

далеко не все

Примеры?

это показатель того, что никакие новые ЯП не способны произвести революцию

(пожимая плечами) А революций вообще было мало, и связаны они не с языками, а с парадигмами.

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

Да неужели? Сейчас за те же деньги можно купить на порядки больше ресурсов.

представь себе, ресурсов больше, но и те же браузеры теперь работают с HTML 5, а не тупо рендерят табличку с текстом, СУБД работают с гораздо большим объемом данных и т.д.

Примеры?

легко - вспомни тему про NoSQL, сам найдешь там примеры для СУБД, насчет компиляторов - вспомни хотя бы про clang, браузеры 20-летней давности это вообще раритеты и т.д.

(пожимая плечами) А революций вообще было мало

(делая удивленное лицо) да ладно

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

вспомни тему про NoSQL, сам найдешь там примеры для СУБД

CouchDB на Эрланге, Cassandra на Яве. Ниша Си++ всё сжимается.

насчет компиляторов - вспомни хотя бы про clang

Изначально они хотели интегроваться в GCC, так что особого выбора у них не было.

браузеры 20-летней давности это вообще раритеты и т.д.

Да ладно? Кодовая база IE примерно такого возраста, то же про Firefox и Opera.

А революций вообще было мало

(делая удивленное лицо) да ладно

Напомни мне штук 5 последних %)

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

Таки c sharp это его официальное название. И из средств разработки под винды наиболее вменяемое

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

CouchDB на Эрланге, Cassandra на Яве. Ниша Си++ всё сжимается.

кто-то говорил, что на других ЯП нет СУБД? они были еще до С++ (что логично), ничего с тех пор не поменялось, и странно делать вид, что новых СУБД на С и/или С++ почти нет, когда их легко можно найти в списке популярных, собс-но о чем и был разговор

Изначально они хотели интегроваться в GCC, так что особого выбора у них не было.

был - C + другой ЯП

Да ладно? Кодовая база IE примерно такого возраста, то же про Firefox и Opera.

я конечно исходный код IE/Opera не видел, не скажу, но webkit, например, взяв изначально KHTML, был полностью переписан с нуля, браузеры вроде Chrome/Safari etc. тоже написаны с чистого листа, Firefox с его XUL тоже не 20 лет, Gecko пожалуй тут самый старый, но и его еще рано записывать в клуб «за 20»

Напомни мне штук 5 последних %)

я забыл добавить один тег к своей фразе

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