Pull to refresh

Comments 166

Люблю запах неконструктивного нытья поутру.

А с учётом того, что у автора, похоже, случился словесный понос, то и запашок посильней кофейного.

ну да, надо смириться и дебажить. Давайте еще скажем, что IPv6 не нужон, нужно просто «конструктивно» напихать в интернет NAT'ов побольше. Как раз-таки называние вещей своими именами и пропаганда нетерпимости к легаси-бреду может дать толчок к уходу в более адекватную сторону в будущем.

Вообще, глядючи на Ваш профиль, вы видимо предельно далеки от фронтэнда. Но вообще мне (как кандидату физматнаук) просто дико удивительно, как человек, который посвятил жизнь алгоритмам, где все заточено на оптимизацию, внезапно называет критику зоопарка HTML/CSS/браузерной совместимости неконструктивной. Казалось бы, хаос как он есть и плевок в лицо всем оптимизаторам, которые трудятся в том числе и для того, чтобы достаточно быстро отрендерить всю ту дрянь, которая напихана в спеках без всякого интереса к тому, удобно ли будет с этим работать. Где Ваше стремление к оптимальности? Мой опыт говорит, что хреново задизайненные вещи приходится оптимизировать целую вечность. А хорошо задизайненные — не приходится в общем-то.

Нерелевантно лично для вас, но неясно, почему неконструктивно. Я понимаю, что чтение препринтов на архиве приучает к выдающейся сухости письменного языка, но с точки зрения презентации — эта будет как минимум очень запоминающейся, это высший класс журналистики и презентации. Это навык. Ученым сложно понять. Но такой текст прочтут в тысячи раз больше людей, чем ваш или мой.
Объясняю. Конструктивная критика — это когда предлагаются пути решения проблем. Без этого это в лучшем случае объективная критика, но никак не конструктивная. «Выкинуть всё и задизайнить заново» — не путь решения проблемы.

P. S. Я не посвящал свою жизнь алгоритмам. Меня волнует счастье пользователей, а оно не так сильно связано с оптимизацией, как многим хотелось бы.
Но проблема-то не техническая! Очевидно, что сделать веб 3.0 с какими-нибудь стандартными json вместо HTTP Codes не проблема. Проблема в головах, в тех головах, которые требуют поддержки IE древних версий. И сам факт пропаганды необходимости уходить от трэша — он уже, на мой взгляд, сам по себе часть решения.
Где вы видели такие головы, которые требуют поддержки IE древних версий? Мне чаще встречается «наш сайт некорректно выглядит в firefox? используйте хром для просмотра нашего сайта, пожалуйста.»
Хехе, только недавно я жаловался своему банку, что их страница для восстановления забытого пароля не работает в Chrome.
Ответили: «мы знаем, используйте IE».
Надо было уточнить, какой именно версией.
А то может они там до сих пор сидят на IE 6.0 с Active X
Забавно. Т. е. если я приду в ресторан и, попробовав там борщ, скажу, что он невкусный — это будет неконструктивная критика и мне надо заткнуться? Чтобы критиковать результат необязательно знать, как именно этот результат был получен — достаточно просто использовать этот результат. Ничего негативного неконструктивной критике нет.
Забавно. Т. е. если я приду в ресторан и, попробовав там борщ, скажу, что он невкусный — это будет неконструктивная критика и мне надо заткнуться?

Затыкаться вам не надо, но именно в таком виде это действительно будет неконструктивная критика. Другое дело если вы хотя бы скажете почему вы считаете что борщ невкусный.
Дык мне то откуда знать, почему он невкусный? Я же даже не знаю, из чего он сделан. Может приправа какая-то не такая, может с овощами что-то не то. Я не повар. Если я не могу сказать, в чём именно проблема, то мне нельзя критиковать? Так и тут. Я могу заниматься frontend-ом, мне может не нравится сам факт, что при малейшем обновлении какого-то заштатного модуля в angular может отвалится пол-сайта, но я не имею права указывать на эту проблему, пока не предложу решения?
Дык мне то откуда знать, почему он невкусный?

Не «почему он невкусный», а «почему вы считаете что он невкусный». Какие-то претензии у вас же к этому борщу имеются?

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

Ну на мой взгляд совсем необязательно предлагать конкретное техническое решение. Но как минимум вы должны указать что скажем если при малейшем обновлении вот этого заштатного модуля перестанет отвалиаться вот эта половина сайта, то с вашей точки зрения проблема будет решена. И это на мой взгляд уже конструктивная критика.
Проблема в легаси, инерции и популярности. Хотя это толком и не проблема даже, а скорее следствие. Слишком большое количество людей начали использовать все эти технологии, и тянуть их в разные стороны, натягивая дальше и дальше это все на глобус. Поэтому и тезисы в статье неконструктивные, — я бы даже сказал, инфантильные. Веб реализует постоянно меняющиеся потребности миллиардов людей во многом благодаря тому, как именно он развивается.
Рискну предположить, что от наличия менее безумных решений веб не пострадал бы никак. «После этого не значит вследствие этого». В масштабах мелкой фирмы такой зоопарк быстро бы все обанкротил, а в масштабах мира почему-то это сразу благо, если следовать вашей логике.
ух какая простыня, аж глаза слезятся
люто, бешено плюсую. Переводчик великолепен.
because you didn’t want to expose your dad as a fraud
потому что вам не хочется выставлять вашего папу жуликом

"Жулик" тут совсем не к месту. Может, "самозванец" или перефразировать с "некомпетентный"…

И всё же местами потерялось многое, из-за ограничений самого хабра.


Например


«Если результат недействителен ([SELECT], раздел 12), следует бросить исключение SYNTAX_ERR ([DOM-LEVEL-3-CORE], раздел 1.4) и прервать этот алгоритм». Подобный романтический этюд в канцелярских тонах, несомненно, будет по нраву людям, тоскующим по тупости списка ингредиентов Доширака, помноженного на многослойную бюрократию Советского Союза. Действительно, можно представить себе мир, в котором производители браузеров нанимают легионы толкователей Талмуда, дабы понять, почему SYNTAX_ERR именно оранжевый, а не лиловый, и как именно эта оранжевость относится к оскобоченной лиловости ([DOM-LEVEL-3-CORE]).

Оригинал:


Но ведь хабр позволяет раскрашивать цвет разными цветами.

Точно. Возможно, автор учтет это и поправит пост.

Разделяя в целом нелюбовь автора к Javascript, не могу не заметить, что автор перегибает палку:
Знаешь ли ты, что JavaScript определяет особое значение NaN («не число»)?
Особое значение, а точнее множество значений «Not A Number», определяет не Javascript, а стандарт IEEE 754, которому кое-как пытаются следовать все языки программирования.
NaN != NaN, так что Аристотель ошибался со всем этим «законом тождества».
Аристотель был бы в шоке, если бы узнал что занимался проектированием арифметики чисел с плавающей запятой для интегральных схем. Поведение Javascript в данном случае полностью соответсвует стандарту:



И если кого-то пугает не выполнимость закона тождества (а также транзитивности, линейной упорядоченности, и еще кучи законов) для чисел с плавающей запятой (а других в Javascript нет), то добро пожаловать в этот мир. У нас тут еще есть -0 и +0, которые как бы равны, но выдают разные результаты при вычислении над ними.

А стандарт определяет NaN таким образом, потому что в Intel 8087 не было инструкции ассемблера isnan. И было не ясно не откажутся ли производители процессоров от стандарта, если её ввести. https://stackoverflow.com/a/1573715/2731452

По ссылке отличный рассказ, но вы его не вполне верно поняли.
В Intel 8087 всё было (младший бит в регистре флагов означал, что результат последней операции — NaN), но примитива isnan не было ни в одном из существовавших языков программирования.
Если бы у правила NaN != NaN не было собственного смысла, сработавшего как мощный аргумент «за», никакое отсутствие isnan() не помогло бы.

Мой ответ уже поправили. Самый мощный аргумент — отсутствие поддержки isnan и литерала NaN в популярных на то время языках программирования. А с введением предиката totalOrder в 2008-м году, без NaN != NaN уже можно спокойно обойтись.

> А с введением предиката totalOrder в 2008-м году, без NaN != NaN уже можно спокойно обойтись.

Ой сомневаюсь. Как раз оригинал про totalOrder:

3) If x and y are both NaNs, then totalOrder reflects a total ordering based on:
i) negative sign orders below positive sign
ii) signaling orders below quiet for +NaN, reverse for −NaN
iii) lesser payload, when regarded as an integer, orders below greater payload for +NaN,
reverse for −NaN.


Поэтому всё пройдёт только при дополнительном условии — все NaN канонизированы — что, в общем случае, не верно. Иначе получится, что +qnan(0) < qnan(1), qnan(x) != snan(x) для любого x>0, и так далее.
Total ordering в IEEE754-2008 нацелен не на лечение проблемы с NaN, а на решение проблемы несравнимости чисто формальным введением сравнения :(

> Самый мощный аргумент — отсутствие поддержки isnan и литерала NaN в популярных на то время языках программирования.

Ну вот я объяснил, почему я не считаю его «самым мощным»: без реального смысла за таким результатом сравнения он был бы ничтожен.
Насколько я понял из рассказа, реальный смысл стандартизаторам виделся как за результатом NaN != NaN, так и за результатом NaN == NaN, поэтому решающим аргументом стала поддержка в ЯП.
UFO just landed and posted this here
> NaN — это как Nothing. А Nothing таки равен Nothing (того же типа).

netch@localhost [(none)]> select null = null;
+-------------+
| null = null |
+-------------+
| NULL |
+-------------+
1 row in set (0.02 sec)

netch@localhost [(none)]> select null is null;
+--------------+
| null is null |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)



Это из MySQL, но в других SQL СУБД будет похоже. Так что эта традиция достаточно древняя и почтенная :)

Равенство != идентичность содержания, а как минимум в JS лёгкой проверки на второй не завезли (и, более того, '===', который должен был быть identity check, превратили в нечто заметно другое).
UFO just landed and posted this here
> А какое из этих отношений у вас включается в какое и в каких контекстах?

В том и проблема, что в современной плавучке ни одно из них не включается в другое.
qnan(0) != qnan(0), несмотря на идентичность.
+0.0 == -0.0, несмотря на неидентичность.

> ИМХО из равенства следует идентичность содержания.

+0.0 == -0.0.

Да, это многих сбивает при изучении вопроса.

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

> А в языках без возможности взять адрес они вообще скорее эквивалентны.

В Java можно взять адрес? (хаки не считаем)

Вполне может быть, что a != b, но a.equals(b) == true.
Да, этой грабле тоже надо учиться — как отвыкать сравнивать строки на `=='.
UFO just landed and posted this here
> Битовые паттерны меня не очень интересуют, если я (без хаков) не могу их наблюдать.

Можете. Например, в C <math.h> есть fpclassify(), signbit(), copysign(), frexp(), ldexp(). Сам стандарт даёт те же методы. Любое значение можно проанализировать, разложить, создать заново. Единственно что — я не вижу методов работы с NaN payload — но это редкая необходимость.

> Это всего лишь значит, что IEEE754 врёт во многих местах.

Где это он врёт и почему? С чего вы это взяли?

> Но если +0 и -0 ведут себя по-разному в некоторых контекстах, то они не равны.

Да, ведут себя по-разному. Например:

atan2(±0, −0) is ±π
atan2(±0, +0) is ±0

Это неудивительно, если рассматривать специфику некоторых функций и то, что 0 == 1/inf в понимании стандарта.

> Java — не образец sound-языка.

Такие проблемы (возможно, с переименованием операций) неизбежно возникают в любом языке на ссылках. Но есть те, что показывают открыто, а могут быть и те, что маскируют. Если вы знаете какой-то другой язык, где не различают идентичность и равенство, значит, там будут спрятаны грабли.
UFO just landed and posted this here
> Так-то я могу и memcpyнуть его в char[sizeof(double)], понятное дело.

Но тогда вы привязываетесь сразу на толпу фактов — на представление в IEEE754 обменном формате (в курсе, что внутренний формат имеет полное право отличаться?), на порядок байт и даже r
на сам размер байта. Ну да, для 4-5 основных платформ будет действовать.

> Но это математически некорректно!

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

UPD: вы рядом упомянули «нестандартный анализ». Я очень вскользь помню, что это, но, кажется, там идея числового кольца не входила.

> Ну вот например там, где ноль — это не ноль, а непонятно что.

Как раз понятно что: «ноль или слишком малое значение», у которого сохранён знак приближения к нулю. Точно так же у INF сохранён знак как указание стороны, с которой приблизились к бесконечности.

Возьмём уже названый пример с atan2: atan2(0, +x) равен 0, но atan2(+0, -x) равен +π для любого неотрицательного x, включая 0. Это очень просто понять, если посмотреть на поведение задачи вычисления угла (а заодно на график арктангенса: где какие разрывы в графике). Нужно было по-вашему делать исключение типа «в нуле вообще нет определения функции»?

> Какого рода грабли мне там ждать?

Всё те же — в реальных задачах требуется проверка идентичности и равенства всего, что не просто плоское значение без поведения; это разные операции.
UFO just landed and posted this here
> Вот люблю, когда люди начинают так выпендриваться, это всегда обещает интересную дискуссию.

А я — нет. Потому что нет никакого «выпендривания», есть просто попытка объяснить чужую логику. Ваша оценка моих действий больше вас характеризует, чем меня.

> Давайте мы с вами возьмём фактор-кольцо ℝ[x]

Не давайте. Речь не о «кольце» в смысле теории групп, речь об отображении на банальную окружность на плоскости. Наверно, лучше было сразу сказать «окружность», просто я уже вспоминал это кусками и за 25+ лет тому назад.
Отображаем (-inf, +inf) на (-1, +1), а его — на окружность единичного радиуса, например, так, что 0 мапится в (1,0); 1 — в (0,1); inf — в (-1,0); -1 — в (0,-1); если u имеет координаты (x,y), то 1/u — (-x,y).
Там дальше это развивалось в том, что аналогичное построение для комплексных чисел давало сферу в трёхмерном пространстве, и на этой сфере вводились интересные топологические результаты. Но я уже не хочу искать это по книгам, моя область сейчас резко далека от всего этого, увы.

> Так в каких реальных задачах-то это требуется?

Я лучше поставлю встречный вопрос: вы знаете язык, в котором одновременно присутствовали бы указатели или ссылки (тут разница неважна) с возможностью сравнения на равенство, и возможность задавать сравнение по содержанию для своих типов, и не было бы разницы между этими двумя действиями?
Если да, и этот язык хоть как-то жив за пределами трёх инвалидов — назовите. По-моему, даже в лиспах есть возможность такой проверки.
Да, я считаю правильным ставить вопрос именно так. Наверно, можно сделать и без контроля идентичности — но будет заметно дороже.
UFO just landed and posted this here
> Обратите внимание — (-inf, +inf), а не [-inf, +inf], такая запись (с открытым интервалом и невключёнными границами) там неспроста. inf у вас никуда не мапится, потому что его нет в домене.

В ℝ — да. Но если сделать маппинг, то появляется одна исключённая точка — а зачем такое нужно? Сделаем для неё значение (тогда левая сторона маппинга будет ℝ+{inf}). Это тоже явно оговаривалось. Увы, я ж говорю — давно было.

> Зависит от того, считаете ли вы хаскель языком с ссылками, например.

Для простоты будем считать, что я его совсем не знаю. И чего именно в нём нет? Проверки на идентичность, по общей логике? Боюсь, где-то на границе с реальным миром она должна появиться.
UFO just landed and posted this here
Но есть другие подходы: например, вещественные вместо числовой оси могут представляться как числовое кольцо, при этом +INF и -INF сходятся в одной точке (INF)
Вам возможно будет интересно, что именно такой подход используется для определения вещественных чисел в стандарте Posit (который задуман как альтернатива IEEE754):

Я видел posit, но считаю его провальным из-за неравномерной точности.
Вообще, надо смотреть на возможное качество реализации в железе и на полный набор эффектов… но я очень сомневаюсь, что переход окупится.
UFO just landed and posted this here
Это неудивительно, если рассматривать специфику некоторых функций и то, что 0 == 1/inf в понимании стандарта.
Но это математически некорректно!
Это корректно даже с чисто математической точки зрения. Infinity, по определению стандарта, это аппроксимация любого вещественного числа, которое больше чем (2−2^−23)×2^127 (для одинарной точности).

И если вы поделите единицу на любое из этих чисел, вы получите число, отличное от нуля, но оно будет апроксимировано к тому что IEEE754 определяет как +0.

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

Значения +0 и -0 это не точки на вещественной прямой, а два разных интервала вещественных чисел слева и справа от нуля. И это единственная пара интервалов из всех возможных значений IEEE754, которая имеет пересечение (в точке 0). Именно по-этому -0 == +0.

Так "==" — это "равно" или "интервалы пересекаются"? Или мы заменяем равенство на "хотя бы частично интервалы пересекаются"?

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

Представьте что вы измерили вольтметром напряжение два раза, и вас получились значения 5.0±0.2 и 5.1±0.1. Эти значения «равны» или «не равны»?

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

Но все эти размышления являются скорее моей вольной интерпретацией стандарта, основанные на знаниях как устроены другие системы представления чисел с плавающей запятой. У авторов IEEE754 скорее всего есть собственное более прагматичное объяснение почему все функции определены так как определены.
UFO just landed and posted this here
Вполне может быть, что a != b, но a.equals(b) == true.
Да, этой грабле тоже надо учиться — как отвыкать сравнивать строки на `=='.

Ну вот это кстати совсем не «грабля» а вполне себе понятная особенность языка. Ссылочные типы и всё такое.
Значит, в JS строки не ссылочный тип, раз там они сравниваются по содержимому, в отличие от остальных объектов?
Если я всё правильно помню, то в JS стринги передаются by value.
Ну может я конечно что-то и неправильно помню, но вроде бы стринги в JS относятся к примитивным типам. А примитивные типы вроде бы передаются by value. Сравниваются уж точно.
Для сравнения, в C# и в Python оператор "==" для строк переопределён для сравнения содержимого на равенство. Но при этом можно сравнить и сами ссылки, если хочется.
У него нет собственного смысла. NaN — это как Nothing. А Nothing таки равен Nothing
Вы не правы. NaN – это совсем не тоже самое что Nothing/Null/None.

IEEE754 определяет множество значений, которым могут выражаться рациональные числа, но не все возможные значения IEEE754 являются числами: NaN, +Infinity и -Infinity не являются числами, хоть и являются корректными значениями типа.

Операции порядка и тождества (>, >=, <, <=, ==, !=) могут быть определены над разными множествами (числа, строки, и т.д.), но далеко не для любого множества выполняется свойство полной упорядоченности (total ordering) и далеко не всегда значение тождества может быть определено для всех пар элементов множества.

Посмотрите на это с точки зрения математики: равна ли «бесконечность» самой себе либо бесконечности полученной другим образом, например умножением первой бесконечности на 2?

Большинство языков программирования ожидают что функции сравнения и тождества (>, >=, <, <=, ==, !=) всегда должны возвращать только булевое значение (true/false).

Ошибочно полагать, что если «a < b» возвращает false, то это означает что a не меньше чем b. Это означает что ответ на вопрос «is a less than b» является false. Это так же означает, что результатом выполнения «a > b» так же может быть false, просто потому что между значениями a и b нет отношения порядка.

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

trait PartialOrd {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering>;
}

Таким образом, если вы попытаетесь выяснить отношение порядка для двух значений чисел с плавающей запятой, у вас может быть четыре варианта результата: Some(Ordering::Less), Some(Ordering::Equal), Some(Ordering::Greater) и None.

И если вы сравните NaN и NaN в Rust, то результатом сравнения будет None, поскольку между этими значениями нет установленной упорядоченности – они не равны, не меньше, и не больше друг друга.
UFO just landed and posted this here
Но я не вижу адекватных причин так делать в 2020-м году
Единственная причина делать так в 2020 – огромное количество алгоритмов ожидает именно такого поведение NaN, как бы всем нам это не нравилось.
Для какого множества отношение тождества не может быть определено для всех пар элементов?
В понимании IEEE754, значение тождества не определено для тех пар чисел с плавающей запятой, у которых хотя бы одно из значений является NaN. Ну и тут еще пару более абстрактных примеров.
А множества без линейного порядка не получится, например, отсортировать. А сортировать флоаты всё-таки хотелось бы.
Ох, не мне вам об этом рассказывать:
fn main() {
    let x = [3.0, 2.0, 1.0];
    x.sort()
}

И результат:
error[E0277]: the trait bound `{float}: std::cmp::Ord` is not satisfied
 --> src/main.rs:4:7
  |
4 |  x.sort()
  |    ^^^^ the trait `std::cmp::Ord` is not implemented for `{float}`

Да, в Rust нельзя просто взять и отсортировать массив флоатов, до свидания.

Насколько я знаю, в других ЯП реализации алгоритмов в стандартных библиотеках используют хаки только ради того, чтобы не сходить с ума от бесконечных перестановок NaN. Rust пошел более жестким путем и тупо запретил все алгоритмы, которые требуют total ordering для float. То есть, float не может быть ключом в бинарном дереве или хеш таблице – система типов не позволит.

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

В классическом анализе у меня нет формального понятия бесконечности, она не принадлежит R (или Q, или N). В нестандартном анализе бесконечность есть, и она вполне равна себе, и её вполне можно умножить на два.

Так что тут либо крестик (и у вас есть +infty, -infty, и на самом деле очень много разных infty, которые вполне конкретно сравнимы и упорядочиваемы), либо трусы (бесконечность нельзя сравнивать саму с собой — но это уже синтаксически некорректно).
Тут я с вами полностью согласен, и на мой взгляд в IEEE754 бесконечность та, которая с трусами и без крестика, просто потому что значение бесконечности есть, а кардинальные числа в стандарт не завезли.

Но IEEE754 со мной не вполне согласен, потому что с их точки зрения бесконечности – это вполне себе числа, в том смысле, что эти значения выражают наилучшую из возможных аппроксимаций вычислений.

То есть это не бесконечности в математическом смысле слова, а множество всех (конечных) значений за пределами динамического диапазона аппроксимированные в два конкретных значения. Точно так же, как множество всех бесконечно малых и близких к нулю значений аппроксимируются в два конкретных значения – +0 и -0.

Так что в IEEE754 бесконечность это число, и она равна сама себе, а NaN – нет.
> Насколько я знаю, в других ЯП реализации алгоритмов в стандартных библиотеках используют хаки только ради того, чтобы не сходить с ума от бесконечных перестановок NaN.

Хаки — нет, а вот специфический подбор алгоритма — да. В каком-нибудь qsort не любой метод разделения подходит.

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

А вот тут вопросик всплывает: у float есть определение тотального порядка, хоть оно и странное. Стандарт 2008 года уже требует поддержки такого сравнения. Как реализовывать такое при таком типаже? Отдельная функция? Я быстрым поиском нашёл такое и такое, но не знаю, насколько они каноничны и соответствуют духу языка (уже факт двух параллельных реализаций смущает).

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

Да, есть такое (второй соответствует требованиям IEEE754-2008 на total ordering, первый — нет). Но это аж никак не отвечает на мои вопросы.
Если бы (гипотетически) стандарт изменил поведение сравнения с NaNs, то все что нужно было бы сделать, это добавить в стандартной библиотеке реализации типажей Eq и Ord для f32 и f64, и все алгоритмы магическим образом заработали. Это если закрывать глаза на нарушение обратной совместимости.

Но так как стандарт не изменяет правила сравнения чисел, а лишь добавляет новую функцию totalOrder, то просто так реализовать Ord/Eq по правилам totalOrdering нельзя, поскольку документация Rust прямо требует, что имплементации Ord/Eq/PartialOrd/PartialEq обязаны быть взаимно согласованы, а мы не можем этого гарантировать, поскольку totalOrder(NaN, x) выдает один результат, а (NaN < x) выдает другой результат.

Конечно, можно (и наверное нужно) добавить новые функции f32::total_order(self, other), но само их добавление мало улучшит жизнь разработчикам, потому что все алгоритмы полагаются на типажи Ord/Eq, которые, как мы выяснили, мы не можем реализовать для f32/f64.

Единственный выход, который остается – добавлять новые типы-обертки вроде тех что вы нашли в стандартную библиотеку, и реализовывать так же все семейство типажей From/TryFrom/Into/Borrow/AsRef/AsMut/Deref/DeferMut, чтобы компилятор во всех случаях сам додумывался запаковывать/распаковывать обертки.

Поскольку в Rust у нас принцип «zero-cost abstraction», эти обертки никак не будут отражаться на производительности программ, и существовать только на уровне системы типов во время компиляции.
> Но так как стандарт не изменяет правила сравнения чисел, а лишь добавляет новую функцию totalOrder

Мнэээ… именно в стандарте, формально новый тип сравнения — наравне со старым, он просто другой для других целей.

С ним получается три вида сравнений: ordered (наличие NaN хотя бы с одной стороны создаёт исключение), unordered (NaN с любой стороны даёт несравнимость, то есть любой предикат сравнения даёт false, но без создания исключения) и total. По умолчанию в большинстве языков (в Rust тоже)? классические сравнения — "==" и "!=" — unordered, а "<", "<=", ">", ">=" — ordered, поэтому про их отличие так сходу со стороны и не заметно. Но в более тонких случаях приходится вспоминать и про них.

Видимо, потому и надо закостыливать, что система типов не позволяет иметь три разных вида сравнения для одного типа? Но тогда и пожелание сделать, например, unordered "<" будет реализовываться такими же костылями.

> Единственный выход, который остается – добавлять новые типы-обертки вроде тех что вы нашли

Ну да, я понимаю, что тут стандартная концепция хромает.
Мне и за пределами плавучки, кстати, приходилось переопределять функции сравнения для особых целей. Я так понимаю, через всякие sort_by проблема решается, но об этом надо всегда помнить (и враппер типа упомянутого поможет и для других типов сравнений, если надо).
Если бы (гипотетически) стандарт изменил поведение сравнения с NaNs, то все что нужно было бы сделать, это добавить в стандартной библиотеке реализации типажей Eq и Ord для f32 и f64, и все алгоритмы магическим образом заработали. Это если закрывать глаза на нарушение обратной совместимости.

Только обратная совместимость никак не нарушается, ведь мы ослабляем требования, а не усиливаем. Раньше нельзя было флоаты ключами иметь, а с такой реализацией — будет можно. Юзер реализацию сломать тоже не выйдет потому что orphan rules запрещают написать такую реализацию для стандартных типов.

Только обратная совместимость никак не нарушается, ведь мы ослабляем требования, а не усиливаем.
Ord/Eq – публичные типажи, и могут находиться в ковариативных и контравариативных отношениях с пользовательскими типами.

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

impl Ord for Foo { ... }
impl Eq for Foo { ... }

fn foo(...) -> Box<Ord+Eq> { ... }

Но в случае контравариативной зависимости обратная совместимость будет нарушена:

fn foo<T: Ord+Eq>(x: T) { ... }

impl<T> Foo for T where T: Ord+Eq { }

Корректность функции foo и реализации Foo for T требуют больше гарантий, чем обеспечивают Ord и Eq после внесенных изменений, и потому обратная совместимость нарушается.

Более простым языком:

fn foo<T, U>(a: T) -> U

Тип foo<T, U> контравариативно зависит от своих типов-аргументов (T) и ковариативно от типа возвращаемого значения (U).

Можно ослаблять требования к типам-аргументам и усиливать требования к возвращаемому типу без нарушения обратной совместимости, но не наоборот.

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

Типажы Eq/Ord определенно инварианты по отношению ко всей кодовой базе, которая зависит от стандартной библиотеки Rust (в совокопнусти). А потому, ни ослаблять, ни усиливать их гарантии без нарушения обратной совместимости нельзя.

Так тут никто ничего не усиливает. Просто для одного из стандартных типов из стд добавляется трейт. Я не вижу, что это должно сломать. Вы раньше не могли использовать f64 в качестве T в T: Ord + Eq, значит от того что f64 им стал ваш код никак в семантике не изменился.


Можно привести конкретный пример кода, который должен сломаться от такой замены?

Ковариантность, контравариантность и инвариантность в Расте относятся только к лайфтаймам. Что-то могло бы сломаться при использовании отрицательных ограничений трейтов (T: !Eq), но в пользовательском коде они запрещены.

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

От этого потихоньку избавляются (Intel в SSE, например, начиная с Nehalem исправляет одну ситуацию за другой). Да и изначально это было всего лишь нежеланием чуть-чуть доработать реализацию.

Где-то я читал лонгрид по поводу этих самых ненормализованных нулей, и intel их продвинула как фичу (где-то в махровые 80ые) — мол, мы умеем считать совсем маленькие числа (меньше, чем конкуренты, которые ненормализованные нули просто игнорили или ругались).

Всё так. Intel вместе с Motorola. У Кахана это расписано.
Но реализация вначале была очень медленной, и только где-то после 2005 это начали исправлять.
ну раз стандарт, то всееее, нахрен логику и здравый смысл. Поздно, прокомпостировали.

Где интегральные схемы, а где высокоуровневые языки, которые через 500 абстракций работают. По-моему классика легаси, единственная причина которой — стремление не думать, а просто брать что кто-то раньше «не подумал».

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

В каждом современном процессоре есть FPU, который воспроизводит поведение Intel 8087, просто потому что если он не будет этого делать, то он либо результаты работы программы будут отличаться от других процессоров (что жесть), либо придется эмулировать поведение Intel 8087 (что медленно).

И когда вы на каком-нибудь высокоуровневом эсперанто вроде Python и numpy перемножаете две матрицы, несмотря на «500 абстракций» между вашим эсперанто и процессором, производительность этого добра упирается в то самое железо, которое работает так как работает.

И у разработчиков языков есть два варианта – либо дать пользователю тип данных для чисел с плавающей запятой, в точности воспроизводящий поведение FPU в процессоре (пусть даже оно все кривое и косое), либо реализовать рациональные числа красиво и изящно и сразу получить просадку в производительности в 10 раз.

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

К сожалению в hardware, в отличии от software, нельзя просто проснуться бодрым как-то утром, сесть за рабочий комп, переписать целиком кусок реализации процессора, выложить в продакшн и уйти на обед. Обратная совместимость тянется десятилетиями, просто потому что что-бы «уйти от legacy» нужно выложить на стол миллиарды долларов (вспомните Intel Itanium).
стандарт IEEE 754, которому кое-как пытаются следовать все языки программирования.
К слову, C/C++ не требуют от компилятора именно этой реализации.
Они и реализацию целых чисел не конкретизируют, раз уж на то пошло.
Поэтому signed overflow — это UB.
Браузер работает как и следовало ожидать. К чему нытьё?
Браво переводчику.

Единственное, что я бы поправил:
наполненные сюрикенами и превращающиеся во львов, едва коснутся земли
Вот да! Во фронтенде творится неимовернейшая хрень и никто не пытается это признать и сделать новые стандарты по уму.
Проблема в том, что «стандарты по уму» окажутся тем самым пятнадцатым стандартом.

Я после прочтения статьи поразмышлял и пришёл к выводу, что это нереально. Предположим даже, что кто-то осилил написать крутейший новый стандарт, и создал под него браузер (достаточно универсальный, чтобы на него перешло большинство народу), и как-то уговорил практически всех вебсайтеров переделать сайты под этот стандарт. Уже ненаучная фантастика, но предположим. Очевидно, что в стандарте будут различные ограничения; невозможно охватить абсолютно всё. Девелоперы начнут роптать: нам надо то, нам надо это, и плевать, что оно не укладывается в рамки архитектуры и авторского видения, что оно усложняет понимание и выглядит абсурдной нашлёпкой сбоку. НАМ НАДО! И не то, чтобы я их обвиняю — стандарт пишется не для красоты, а для совместимости реализаций практических задач. Но в итоге, если автор стандарта поддастся, то мы будем иметь то же, что имеем сейчас. А если нет, то найдётся Гугл кто-то, кто скажет: возрадуйтесь, девелоперы, я сделал свой браузер, поддерживающий эту шнягу, а то, что оно вне стандарта — ну и фиг с ним, расширим стандарт своими силами. И сколько времени после этого проживёт исходный красивый и элегантный стандарт?
UFO just landed and posted this here
Предположим даже, что кто-то осилил написать крутейший новый стандарт, и создал под него браузер

Ну или например мы забываем про такое явление как «браузер» и ищем какой-то принципиально новый концепт.

Гипертекстовый векторный фидонет? (ц)
Проблема 15-го стандарта в том, что нету какого-либо органа, принуждающего соблюдать стандарты. Без него сколько стандарты не принимай, они все будут иметь только рекомендательный характер.
Было бы конечно хорошо такой орган создать, но это уже совсем другая история.
Тут ведь исходная мысль какая: стандарт пишется для общего удобства. Если все соблюдают стандарт, всем хорошо и радостно. Не хочешь соблюдать? Имеешь на то полное право, но тогда не удивляйся, что взаимодействие с теми, кто соблюдает, будет ограничено или вовсе невозможно. Иногда это приемлемо (для себя лично, для каких-то внутренних задач…). Разумный подход для разумных людей. Вот только, как показывает история, в массовом сегменте разумные подходы срабатывают крайне редко.

А запретиловка — палка о двух концах. Ну запретили какой-нибудь флэш, а альтернативы не предоставили. И что делать? Девелоперам плохо (HTML5 недостаточен, canvas тормозит, webgl глючит); пользователям плохо (нет любимых игрушек, чтобы просто открыл страничку и поиграл); стандартизаторам плохо (их непрестанно клюют и те, и другие)… И кто выиграл? Только те, кто видит стройный и красивый стандарт без кривого флэша. Стоило оно того? Я, например, совершенно не уверен. (Пример полностью условный, разумеется.)

Проблема явно сложнее и не решается подходом «да взять всё и поделить».

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

К сожалению, на мой непрофессиональный взгляд, сказанное тут про браузеры правда. Браузеры усложняются, добавляется куча «крутых, модных» фич, и с очередным обновлением веб браузер жрёт всё больше памяти. Браузерные движки уже невозможно нормально обслуживать, из за количества кода, а вероятность появления нового браузерного движка стремится к нулю со скоростью света создания копий браузера google chrome, только с изменением цвета фона.
На момент появления Google Chrome тоже все говорили, что «вероятность появления нового браузерного движка стремится к нулю со скоростью света создания копий браузера mozilla, только с изменением цвета фона.»
Так нового и не было, KHTML появился где-то в районе Gecko. Вопрос конечно, что от него осталось, но в целом корни то оттуда
Мазафака. Этот негр воображает себя Львом Толстым. Дальше фраза из Льва Толстого для сравнения
Стоя в холодке вновь покрытой риги с необсыпавшимся еще пахучим листом лещинового решетника, прижатого к облупленным свежим осиновым слегам соломенной крыши, Левин глядел то сквозь открытые ворота, в которых толклась и играла сухая и горькая пыль молотьбы, на освещенную горячим солнцем траву гумна и свежую солому, только что вынесенную из сарая, то на пестроголовых белогрудых ласточек, с присвистом влетавших под крышу и, трепля крыльями, останавливавшихся в просветах ворот, то на народ, копошившийся в темной и пыльной риге, и думал странные мысли.

Что происходит? Неделю не выходит новый JS фреймворк и все решили его поносить?


Статья конечно веселая, но на практике от половины описанного спасает простой eslint.


Number.prototype.valueOf = function(){return 42;};

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


Кроме того, JavaScript определяет два оператора тождественности (=== и !==), не выполняющих приведения типов, выполняемого стандартными операторами равенства; однако, NaN !== NaN.

Да, учил разницу между == и === несколько лет, а NaN вообще магия. Не понимаю, как что-то, может быть не числом


Хоть каждое предложение нарезай и угарай поверх его мыслей

Никоим образом не относясь непосредственно к разработке фронта, мне таки приходится периодически его деплоить и немножко суппортить. И примерно раз в полгода вспоминается мне вот этот доклад в частности: https://events.yandex.ru/events/yac/2013?openTalkVideo=252-37

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

Удивили. Неужели вы с Date столкнулись до того, как познакомились с массивами, например? Уж больно типична нумерация с нуля, на моей памяти, кажется, элементы массива с единицы считали только в некоторых бейсиках, фортране и паскале (ну, там явно диапазон указывался).
  • Месяцы не подразумевают массивы, где можно было бы ожидать такое поведение
  • У дней месяца такой проблемы почему-то нет
  • У конструктора есть форма с параметром строкой, где такой проблемы тоже нет.
В целом соглашусь, но зная, что массивы начинаются с 0 – не воспринимаешь нумерацию месяцев с 1 как единственно возможную.
Т.е. считать нумерацию месяцев с нуля неудобной я могу (хотя и маленькие плюсы в ней есть), а вот удивляться ей – нет, и заглянуть в документацию, чтобы выяснить, как нумеруются месяцы, для меня естественно.
Удивление вызывает необоснованность и локальность такого решения. Искать подобные подвохи в документации — это противоестественно.
А у кого-то вызывает удивление использование где бы то ни было нумерации с единицы: она же не ложится на массивы. Скажем, массив названий месяцев на государственном тундрюкском языке, или количества родившихся в каждом месяце. И он считает необоснованной нумерацию с единицы.

Так что если у вас нет рефлекса подмечать такие опасные места (где одному покажется естественным одно, а другому другое) и кажется противоестественным лезть в этом случае в документацию – вам тяжело.
Это не вкусовщина, чтобы делиться на «нравится»/«не нравится». Если у такого неконсистентного решения нет практической выгоды, то оно необосновано.
Это тоже, кстати, не более, чем дань привычке в таком высокоуровневом языке, как JS. Но я допускаю, что изменение этого ожидаемого поведения может приводить к ошибкам. А с Date у JS свое персональное «хау-ноу».
Можно легко предположить что автору хотелось вот такого:
const monthNames = ['Январь', 'Февраль', ...]
months.map(n => monthNames[n])

Я больше одного раза видел в чужом коде (по-моему в пхп) месяц Нулябрь в начале массива, потому что нумерация месяцев с 1, а нумерация массивов с нуля, а жизнь — борьба.

Алсо если бы нумерация начиналась с 1, то кто-то другой (или даже вы сами) написали бы точно такой же комментарий, про удивление, необоснованность и противоестественность. Потому что всем не угодишь.
UFO just landed and posted this here

Рискуя быть занудой:


$months = [1 => 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];

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

UFO just landed and posted this here
Только надо учитывать, что это ассоциативный хэш, а не массив, и поэтому доступ по индексу выполняется в несколько раз медленнее.

Чем где? В PHP любой массив всегда ассоциативный, что ты с ним ни делай.
Впрочем, они их хорошо оптимизировали, потому производительность – далеко не главная проблема такого архитектурного решения.

Вы ничем не рискуете: я застал переход с пхп 4 на пхп 5, до появления такого синтаксиса оставалось меньше 10 лет…
Вы ничем не рискуете: я застал переход с пхп 4 на пхп 5, до появления такого синтаксиса оставалось меньше 10 лет…

Да, квадратные скобки как замена array() появились в PHP 5.4, но вовсе не в этом суть.
Ну хорошо, вот, это будет работать хоть на PHP 4:


$months = array(1 => 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь');

Я это увидел на башорге.


В коде не встречал, т.к. в Java есть логичные enum-ы, а в javascript стараюсь не заглядывать — не люблю я его.

Осталось выяснить, из кода это пришло на бор, или же с бора в код.

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

Да ладно, месяцы с нуля или с единицы – это как думать, бороду во сне на одеяло класть или под одеяло. Так и так неудобно.

Если у меня есть дата, к примеру, 17.03.2020, то в конструктор new Date(year, month, day) я должен передавать числа 2020, 3 и 17. Других чисел у меня нет. По крайней мере, я в упор не вижу.
Всё остальное ненормально. Всё остальное или шизофрения, или психопатическое желание поиздеваться над джунами.

Вот бы сейчас задумываться, какой там номер у месяца…

Если это константы в коде, то используйте библиотечные константы.
Если оно пришло вам в виде строки, то парсьте не руками, а специальным библиотечным парсером, который умеет правильно парсить.
Если вам надо из даты(объекта) собрать такую строку, используйте специальный библиотечный форматтер, который умеет правильно форматировать.
Если оно пришло вам в таком виде(год месяц число) извне отдельно — страдайте используйте java.time.Month.of.
> Выяснил, что этот идиотизм с нулевым месяцем пришёл из большой Джавы.

Он появился в изначальном Unix. А вот почему дальше его копируют 1:1 — вопрос интересный :)

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

У вас Python? Там зачем-то сдвинули отсчёт даже в одноимённой структуре :)
А на Java вы зря бочку катите, вот остановится развитие по Муру — сначала начнут дохнуть все чисто динамические языки.
Он появился в изначальном Unix. А вот почему дальше его копируют 1:1 — вопрос интересный :)

Здесь просто напрашивается басня про шатл и лошадиную задницу.

Можно ещё вспомнить, что в VBA коды ошибок унаследованы — через длинную вереницу бейсиков — из Microsoft BASIC-80; поэтому их нумерация начинается с 3 и идёт с пропусками.

Если бы автор разрабатывал во времена IE6, он бы знал, что сейчас — рай.

Во времена IE6 поддержки одного IE6 было достаточно для 95% аудитории.
Сложности начались, когда появился зоопарк разных браузеров.
UFO just landed and posted this here
Самая сильная часть в этом рассказе про экоактивиста, который столкнулся с суровой реальностью. :-)
Шедеврально. Можно растаскивать на цитаты

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

В качестве альтернативы он предлагает написать новый веб с нуля. И, да, это смешно.
Э… Где? Я был невнимателен или это в других статьях того же автора?
В заголовке и последнем слове. Всё по канону.
ну, с нуля не с нуля, но олдскульный треш должен как-то уходить.
Ну вот, например, ФФ бодрее выпиливает deprecated, а люди продолжают так писать, ведь самый массовый браузер поддерживает.
Если ФФ неправильно показывает мой любимый сайт, то что я сделаю?
а) убедю хозяев сайта его переписать; или
б) выкину ФФ и поставлю браузер, который показывает мой любимый сайт правильно?
Б. Вариант Б. Это значит, что браузерам для успешности нужно тащить как можно больше легаси. Пока не останется только один, владельцы которого всех заставит ходить через свои сервера, и (не обязательно, но возможно) писать сайты как они скажут и на чём скажут. По крайней мере, так им мечтается.
Вот и sumanai пишет в ветке выше: «Сколько ни сообщал о багах работы сайтов в Firefox, ни разу нигде не поправляли.»
«Чем ты ближе к земле, тем ближе к тебе черви».
интересная статья, спасибо за перевод!
После прочтения включил везде «use Strict» > Исправил все баги в Chrome > Проверил другие браузеры > Выключил «use Strict» от греха подальше…

Сдается мне, что JavaScript повторит судьбу Visual Basic и будет вытеснен другими языками (Dart, TypeScript, Kotlin и прочими), которые в будущем тоже будут нативно поддерживаться браузерами. И в один прекрасный солнечный день JavaScript отключат как отключили Flash. И причиной как и тогда будет security.
У того, что Microsoft прекратила развивать Visual Basic, не было никаких объективных/технологических причин.
Просто сменилась мода снаружи MS и вкусы руководителей внутри MS.
Да, во многом вы правы, дело тут не совсем в технологии.

VB (как и JS) был достаточно легок в использовании, что привело к тому, что его стали применять большое количество людей далеких от программирования. Офисные сотрудники, новички и студенты пилили свои программы и скрипты и повсюду развешивали спагетти-код. А VB не делал ничего, чтобы помешать укоренению их плохих привычек. Это привело к падению репутации языка и его медленному угасанию.

Те же самые симптомы, к сожалению, наблюдаются у JavaScript — на нем слишком легко писать плохой код и это сильно бьет по его репутации.
Так VB был создан как раз для того, чтобы домохозяйка могла налабать себе скриптец в Excel.
Офисные макросы — это VBA (Visual Basic for Applications). А на самом VB лабалось немало прикладного софта под винды в свое время.
В «отдельном» VB по сравнению с VBA только добавлялся компилятор, и заменялась стандартная GUI-библиотека. Сам язык при этом был один и тот же.
Цель создания разная. VBA — это не весь VB.
Хотелось бы добавить, что я нисколько не принижаю JS как язык, он в чем-то прекрасен и дает большую свободу. Но это его достоинство в не очень умелых руках среднестатистических кодеров приводит к созданию тяжелоподдерживаемого и глючного кода. Я встречал много талантливых людей которые пишут на JS прекрасный чистый код, но, к сожалению он тонет в тоннах спагетти кода, созданного большинством, что серьезно бьет по его репутации.

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

Языки со слабой типизацией весьма хороши для быстрого создания прототипов, MVP и небольших проектов — на них всё можно сделать все очень быстро. Но когда проект разростается до сотен тысяч и миллионов строк когда, вероятность ошибок растет геометрически.

Обьем кода на веб страницах сейчас быстро растет и слабая типизация уже не лучший вариант. Откройте консоль при работе на сайтах банков — ситуация, как заметил автор, весьма и весьма печальна — она очень сложно контролируемая, что уж говорить про большинство сайтов.
C++ — язык с достаточно строгой типизацией?
С++ это язык со слабой типизацией и в больших проектах это тоже источник большого количества сложно-уловимых ошибок. Но в отличии от JavaScript там больше опытных разработчиков, которые выработали свои определенные правила кодирования, некий безопасный подъязык. Но и это не особо помогает и идет постепенная миграция в сторону Rust.

Языки с достаточно строгой типизацией это Java, Kotlin, C# (TypeScript вроде как тоже). Если мы говорим про банковский сектор и кровавый интерпрайз — это в основном Java. Причем уровень разработчиков даже в банках мирового уровня весьма и весьма посредственный, но типобезопасность наряду с TDD дает приемлемое качество, маштибируемость и довольно низкую стоимостью поддержки.

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

UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
который каждый раз скачивается и компилируется

WASM поддерживает динамическую линковку.
UFO just landed and posted this here
Это печально, конечно, но даже в самом плохом случае (совместимость ABI ломается каждый раз), в рамках одного билда кэширование таки будет работать.

Ну или Mono, который пусть и вестит тонну (пока встроенный GC в WASM не завезли), но агрессивно кэшируется и абстрагирует системный ABI, позволяя исполнять .NET-сборки без оглядки на него.
Боже, самая уродливая статья, что я здесь когда-либо читал. Попытки автора оригинала постоянно шутить и нон-стопом приводить абсолютно не уместные сравнения/аллегории/etc просто нереально(использую здесь модное, но чертовски актуальное словечко) «душат». И если весь этот балаган и камеди-клаб отбросить, то от статьи останется очередное, ничем не отличающееся от других, нытье про несовершенство текущего веба. Ну и куда же без тычка в сторону JS? А тот момент, где автор намеренно изменяет поведение прототипа объекта, а потом жалуется, что все работает не так и винит во всем JS — просто шедевр.
В оригинале это всё реально смешно! Отличная стёбная статья, вы чего, люди?
«Quirks mode» это не «Вычурный режим». Лучше «Режим совместимости» или не переводить вообще.
Приложеньице запущено.

TL;DR о чем речь — можно резюмешку плиз ?

UFO just landed and posted this here

Спасибо. Можно было не писать — это и так очевидно (в смысле не про ваш коммент, а про статью) )

Классный перевод и чтиво на ночь :))) Спасибо!
Sign up to leave a comment.

Articles