- 1
https://sun1-28.userapi.com/c854224/v854224060/1a2490/7JEShAFqoEU.jpg
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+1
https://sun1-28.userapi.com/c854224/v854224060/1a2490/7JEShAFqoEU.jpg
Сишник половину из этого увидит логичным.
А JS макаки без должного математического образования не знают даже, как правильно проверять на эквивалентность floating point numbers.
Я за «сильную типизацию» и против «слабой параши».
Кстати, инфиксных выражений в самом Tcl нет, их считают через функцию expr, и работают там только числа. Можно переопределить функцию expr и считать ей как угодно и что угодно. Не то что в этой вашей анскильной пайтушне.
https://github.com/aemkei/jsfuck
Бонус для языка с более сильной типизацией:
https://github.com/wanqizhu/pyfuck
Вообще, не могу понять, зачем нужно лезть в это ISO кроме понтов "Мы — международный стандарт?"
Признайся, это была единственная документация, что ты когда либо видел.
Приведи реальный пример лучшей документации.
https://docs.python.org/3.8/
Единственная пользительная штука в документации к «PHP» это мини-версия so в комментах.
https://docs.python.org/3.8/library/threading.html
Где блядь кусок кода, демонстрирующий как мне посчитать x**2 for x in range(10) параллельно? Он должен быть в начале статьи.
Мануал по языку "python" не предназначен для произвольного доступа. И это в то время, когда этот язык рекламируют для быстрого наговнячивания скриптов и SO-программирования. Мануал по языку "python" отвечает требованиям к языку чуть менее, чем никак.
- Нет списка классов в одном месте
- Нет списка функций в одном месте
- Есть только длинная портянка текста, из которой можно выкусить эти списки только юзерскриптом с document.querySelectorAll
+ Есть примеры, даже несколько
В мануале на php.net такого говноподхода нет. Разве что в списке функций есть только имена, а нет сигнатур.
+ Есть классов в одном месте
+ Есть список функций в одном месте
- В списке функций есть только имена, а нет сигнатур.
+ Есть примеры, даже несколько
С php.net может потягаться только cplusplus.com. Там иерархия модулей/классов раскрывается без перехода на новую страницу. И такая ориентируемость на произвольный доступ для нетривиального языка, где для старта требуется много последовательного чтения.
Тогда для сравнения нужно в остальных примерах тоже показать недокументированные функции. Как минимум у WinAPI недокументированные функции есть.
https://www.php.net/manual/en/function.register-tick-function.php
Какой тик? Какая, блять, функция, с какой сигнатурой? Что за второй параметр с типом mixed? Догадайся сам и напиши об этом в комменты <3
Функция с любой сигнатурой (смотри про параметры выше), можно даже использовать члены класса если первым аргументом передать массив [объект, член-класса] (пример на странице документации)
Тик — это неведомая ёбаная хуйня, которая происходит когда интерпретатор немного поработает. (ссылка есть на странице документации)
Мне приходилось читать много хуёвой документации.
Специально самую хуёвую страницу нашел, молодец
+ Список методов и полей
+ Список модулей
+ Примеры
>>> В сипайтоне одновременно может работать только один поток.
Если у тебя есть четырёхъядерный проц, и в языке без «GIL» ты начнёшь считать сумму охуенного массива в четыре потока, то посчитаешь её в четыре (на самом деле меньше, но это не важно) раза быстрее, чем если бы считал одним. В «Python», запустив суммирование на четырёх потоках, никакого увеличения производительности ты не получишь.
А ещё они любят сделать демо-проект, зипануть его и выложить с минимумом комментариев. Потому что время индусов из Купертино слишком дорого, чтобы тратить его на такую ерунду.
> https://perldoc.perl.org/perlfunc.html#lock-THING
Какая-то каша из говна и мёда.
+ наборы функций объединены в списки
+ всё на одной странице, удобно искать
- недоструктурированная каша, сигнатуры не на первом месте
> https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
Более-менее адекватный вариант, но могло бы быть и лучше.
+ удобная иерархия слева
- сигнатура не на первом месте
> https://man.openbsd.org/pf.4
Адище, в котором ни черта не выцепишь, пока не прочитаешь от корки до корки.
- недоструктурированная каша
+ есть разделы и чётко видно, где какой ключ начинается/заканчивается
> https://developer.apple.com/documentation/uikit/uisplitviewcontroller
Недоструктурированная каша. Это класс, где тогда сука список полей и методов? Адище, в котором ни черта не выцепишь, пока не прочитаешь от корки до корки.
- длинная портянка, где поля и методы употребляются где-то между делом
+ в See Also есть какой-то логичный список (троллинг такой?)
> https://www.php.net/manual/en/function.vpopmail-add-domain.php
Более-менее адекватный вариант, но могло бы быть и лучше. Хотя, поудобней майкрософтовской.
+ сигнатура на первом месте
+ структурированная питушня
https://forth-standard.org/standard/core/DOES
Тут тебе и описание, и комментарии и примеры.
Возможно, ты путаешь слабую и динамическую типизации. Не путай.
При динамической типизации хранится пара (тип, значение).
>> если в repl питона забить "1" + 1 будет ошибка рантайма а не компиляции
В принципе, конкретно в данном случае, когда выражение состоит из констант, могли бы реализовать и анализатор этапа компиляции. Почему не реализовали, вопрос отдельный.
В общем же случае, когда выражение из переменных, проверить сможем только в рантайме.
>> чем это лучше js в котором просто неявно реализованы методы приведения
Это позволяет ловить ошибки. Лучше явно указать, как я хочу преобразовать один тип в другой, чем гадать на кофейной гуще, что же получится.
Что мы хотим получить из "1" + 1: число, строку или что-то ещё? Плюс в данном случае означает сложение, конкатенацию или что-то ещё?
Меня в немногословном питоне бесит, что вместо
или даже развёрнутого
надо писать
или
Пусть у нас есть какая-нибудь функция, например:
И вот какой-нибудь невнимательный программист допускает ошибку:
Он попросту забыл, что в форме хранятся ещё нераспарсенные данные в виде строк. В нормальных языках (с сильной типизацией) на этом месте программист получит ошибку сразу после запуска и пойдёт фиксить. В языках со слабой типизацией язык решит, что он умнее программиста, и выдаст какую-то поебень, которая ещё сто лет будет создавать непонятные глюки.
Собственно, то, что слабая типизация — говно, умные люди поняли уже давным-давно, и именно поэтому сделали «Typescript».
Это важно, чтобы понимать что js отличается только механизмами приведения типов
>Он попросту забыл, что в форме хранятся ещё нераспарсенные данные в виде строк. В нормальных языках (с сильной типизацией) на этом месте программист получит ошибку сразу после запуска и пойдёт фиксить. В языках со слабой типизацией язык решит, что он умнее программиста, и выдаст какую-то поебень, которая ещё сто лет будет создавать непонятные глюки.
Этот пример абсолютно ничего не значит, потому что с таким же успехом можно придумать пример в котором это полезно. Падает или не падает программа - это абсолютно не важно с точки зрения требований к программе так как оба результата в сущности неверны
>Собственно, то, что слабая типизация — говно, умные люди поняли уже давным-давно, и именно поэтому сделали «Typescript».
Typescript - это статический анализатор, по сути. Его не остается после компиляции и проверку типов при компиляции можно нахуй отключить. Это другая парадигма относительно питона и других скриптовых языков
Иначе сильная типизация только уменьшает вероятность работы программы.
Без неё на сервер бы отправилось какое-то говно или клиету бы отобразилось какое-то говно. Пользователь увидел бы, что у него сняли 510 рублей вместо 16 и пожаловался бы в техподдержку. А так оно просто упадёт, пользователь подумает, что кнопка не реализована.
Однако лично я, например, предпочту, чтобы сбоящее приложение упало вместо отправки произвольной суммы куда-нибудь в Эфиопию. Потому что возврат денег — это адская ебля, как для клиента, так и для компании.
> А так оно просто упадёт, пользователь подумает, что кнопка не реализована.
Ну естественно, если писать в «JS-way», игнорируя любые ошибки. А нормальные люди™ в случае непредвиденных исключений извиняются перед Кадыровым пользователем и шлют краш-репорт.
Кстати, а как его правильно послать?
* Пользователь (а то и анонимус) может послать туда любую питушню и затроллить сервер
* Если разрешить отправлять только залогиненным, то мы никогда не получим сообщение о том, что пользователь не смог залогиниться из-за ошибки.
А от желающих посрать ничего не поможет, только бан.
На этом слайде какой-то высер который никогда никому не помешает в работе, все "бытовые" приведения типов легко умещаются в мозгу любой веб-макаки. А уж если ты решил складывать массивы с объектами - будь добр почитать стандарт
Плюс не обязан быть везде коммутативен, если это не нарушает аксиоматики. Как понимаешь, аксиоматики арифметики массивов и объектов не существует
> Уверен, программист на PHP, Cobol или C++ точно так же скажет про любой изьян языка.
Я не согласен с тем что это изъян языка
> Кстати, что там с типом null? Уже исравили?
А что с ним?
Что значит "нормальная семантика"?
> Большинство людей привыкло к коммутативности операции сложения.
Еще раз: плюс не обязан быть коммутативен там где это не обозначено аксиоматикой. Я не понимаю к чему привыкли люди, которые вычитают строки из чисел
>С ним вот.
https://2ality.com/2013/10/typeof-null.html
Не математик, но вот векторное произведение некоммутативно. Примеров именно сложения не знаю.
>Ну вот я и попросил пример. Хочется узнать про такое множество, для элементов которого определена операция "+", и она не коммутативна.
https://en.wikipedia.org/wiki/Near-ring
Операция "+" определена и не обязана быть коммутативной
>Или теперь ты скажешь, что typeof не обязана быть обратной от instanceof ?
Я хочу сказать что typeof давно неофициально deprecated, была признана ошибкой и ее похоронили без почестей. В современном js это просто мозгоебалка для собеса
Добавлю что это значит что ты полностью прав и это говно, но это не должно быть единственной причиной для хейта js, особенно новых стандартов
Именно, у кольца коммутативен, у около-кольца - не обязательно
>чото не написано нигде такого. Откуда дровишки?
Ударение на слово неофициально. Это значит что сам создатель языка признал это говном и не рекомендует к использованию
> Но JS не консистентент
Жду еще примеров
>
>Из твиттера автора?
Нет, ты можешь продолжать писать typeof null и рассказывать всем какое js говно
>Двух недостаточно?
>что дает сложение пустых массивов, и какой пункт спеки про это говорит?
Я уже высказал свое мнение по поводу сложения и привел в пример near-rings, пожалуйста, не приводи эту хуйню в пример
Что дает [] + [] мне не очень интересно, думаю, что пустую строку
Это не является примером неконсистентности
Не пойми меня неправильно: эта хуйня работает, тебе никто не запрещает ей пользоваться. Я уже признал что это говно, это признал создатель языка и скорее всего на работе на тебя косо посмотрят или нахуй пошлют. Уверен, во многих языках есть такие же конструкции и решения, которые существуют но не очень приветствуются в кодовой базе
>В каких языках бывает ситуация, в которой опытный программист не может сказать, чему равно сложение двух встроенных типов?
Вот прикинь, js-программисты не сидят целый день и складывают массивы с массивами
>Почему, кстати?
По той же причине, что и "1" + 2 === "12" - интерпретирование плюса как конкатенации. Вангую что []-[] === 0 по той же причинеи аналогично числам и строкам. Консистентность!
Я не джаваскриптер, но помню, что плюс сначала проверяет оба аргумента на число, потом пытается вызвать valueOf, потом — toString, и всё это переплетено и перемешано так, что хрен запомнишь. Собственно, чем дальше плюс заходит в своих эвристиках — тем неадекватнее получаются результаты, вплоть до преобразования обоих аргументов в строки и их последующей конкатенации.
UPD: Во, нашёл это говно: https://dmitripavlutin.com/javascriptss-addition-operator-demystified/. Какой пиздец )))
Details:
URL https://dmitripavlutin.com/javascriptss-addition-operator-demystified/
Domain dmitripavlutin.com
IP 142.93.108.123
Decision 2-6-27/ 2016-07-25-70-АИ made on 2016-07-25 by ФНС.
This block affects IP 142.93.108.123 and domain bkdostup.ru.
Decision 2-50 made on 2018-03-05 by суд.
This block affects IP 142.93.108.123, domain downloadfreegreen.bitballoon.com and URL http://downloadfreegreen.bitballoon.com/instrukciya-samus-725-g.html.
Decision 2-6-27/ 2016-01-31-6-АИ made on 2016-03-09 by ФНС.
This block affects IP 142.93.108.123, domain primedice.com and URL http://primedice.com.
Decision 2019-08-22-1780 made on 2019-08-28 by МВД.
This block affects IP 142.93.108.123 and domain rollsafe.org.
Я могу привести пример неадекватной неконсистентности плюса:
Очевидно, что для консистентности в последнем примере результатом должно быть «"123456"»: сложение объектов намекает, что в «JS» операция «+» — это «преобразовать-в-строку-и-конкатенировать», в отличие от:
Кстати, без рофлов, а что вот это за хуйня?
>Кстати, без рофлов, а что вот это за хуйня?
> {'a': 'b'} + {'c': 'd'}
Типы привелись к строке
> {'a': 'b'} + 'lol'
Выражение интерпретировалось как блок кода
> let hui = {'a': 'b'};
undefined
> hui + 'lol';
Типы привелись к строке
Унарный оператор перегружен: он может означать сложение (математическую операцию), а может означать и конкатенацию. Конкатенация строк — это не сложение, просто так совпало, что в JS для неё выбрали тот же знак, что и для сложения. Есть языки программирования, в которых конкатенацию обозначили другим знаком.
Лол. А это беда консоли, или в скрипте такой же багор будет?
> Еще раз: не существует никакой аксиоматики сложения хуя с жопой, с числами "+" работает нормально. То что поведение математических операций на каком-то говне отличается с вашими ожиданиями - это ваши проблемы.
«+» — это операция сложения. Складывая два объекта, любой нормальный человек (не писавший на «JS») ожидает, что два объекта сложатся. В «Python», например, если я к одному списку прибавлю второй, я получу адекватный и, главное, полезный результат. А вот в «JS» я получу хуйню, которая абсолютно бесполезна. Не существует реальных примеров кейсов, в которых такое идиотское поведение можно использовать.
Собственно, это и есть философия «JS»: в любой непонятной ситуации выдать программисту хоть какую-нибудь хуйню, пусть даже полностью бесполезную и неадекватную, вместо нормального сообщения о том, что получается хуйня. Именно поэтому я против «JS».
Думаю, что да, в скрипте будет так же
>«+» — это операция сложения. Складывая два объекта, любой нормальный человек (не писавший на «JS») ожидает, что два объекта сложатся.
По-моему, вы там все ебанулись
>В «Python», например, если я к одному списку прибавлю второй, я получу адекватный и, главное, полезный результат
От этого само понятие "сложение списков" менее идиотским не становится
Вот, можешь использовать во всех кодовых базах
Ой, вот не надо формальную математику приплетать. В «JS» даже целые числа формально не соответствуют математике:
В отличие от «Python», где длинная арифметика искаропки.
Проблемы от этого только в случае с % и с пирформансом для менее продвинутых версий с интерпретацией вроде JScript (хотя, python всё равно больше тормозит), где добавляются лишние касты.
В остальном же одни плюсы вроде прозрачных опереций и отсутствия потери точности 32битных интов.
Ну вот возьмём, скажем, C/C++:
1 - это натуральное число
1 - это целое число
1 - это рациональное число
1 - это действительное число
1 - это комплексное число
1 - это гиперкомплексное число (...нион)
1 - это матрица размера 1*1
1 - это тензор размера 1*...*1
И при работе с числами выбирается наименьшее требуемое множество (примерно как работает умножение в numpy). Это удобно и убирает всякую питушню вроде явных кастов там, где прописаны математические правила.
Чуть менее, чем всегда пользователю нужно 1/2 = 0.5, и по идее нужны явные литералы челых чисел вместо говна вида 1/2 = 0.
1 = double
1.0 = double
1. = double
(int) 1 = int
1i = int
Потому что целочисленное деление aka div тоже нужно и полезно.
А с дефолтным даблом не соглашусь — это слишком неочевидное решение. Потому что для пользователя 1 — это в первую очередь целое число: точки-то нет.
Но в то же время 1/2 = 0.5.
Наименьшее требуемое множество
1 in N
-1 in Z
1/2 in Q
Целые числа удобны своей точностью и предсказуемостью: с поправкой на mod 2^N ты всегда можешь их точно складывать, вычитать, умножать и целочисленно делить, не беспокоясь, что в один прекрасный день у тебя внезапно исчезнет единица или чего покрупнее. А плавучка (в любом современном железе) — говно, использовать которое можно только от полной безысходности.
В js нету типа "целое", и "литерала-целого" тоже нету
А длиннопитухи из пистона тормозят!
P.S. То ли дело Haskell. Int - как в программировании - быстр и короток, Integer - как в математике - длинен и медленен.
Но они есть!
На работе только этим и занимаемся
Ну тогда записывай в жсобагры.
> По-моему, вы там все ебанулись
А что для тебя неожиданного в том факте, что, складывая два объекта, нормальный человек ожидает получить их сумму, а не какую-то непонятную хуйню?
> От этого само понятие "сложение списков" менее идиотским не становится
С чего это оно «идиотское»? Такое поведение — полезное и удобное. Подойди к любому программисту (не писавшему на «JS», конечно) и спроси, что он ожидает получить в качестве результата выражения «[1, 2, 3] + [4, 5, 6]».
Хорошо, даже если ты считаешь, что это понятие идиотское — тогда почему «JS» возвращает абсолютно бесполезную хуйню, вместо внятного «HuinyaException('Bbl nblmaemecb cgeJlamb xyuHl0')»?
> [].__proto__.toString = () => {throw "go fuck yourself"}
Ну вот мы и начали фиксить баги жаваскрипта.
Но насколько я знаю, это всё уже есть в «Typescript».
Это просто невалидный синтаксис. В других языках не существует невалидного синтаксиса?
>А что для тебя неожиданного в том факте, что, складывая два объекта, нормальный человек ожидает получить их сумму, а не какую-то непонятную хуйню?
Я не понимаю что такое "сумма двух объектов". Что такое сумма матриц - понимаю, что такое целое - тоже. Как сложить {"a": 1} и {"b": 2} и произвольные два объекта - не понимаю. Вы в своем питоне все подряд можете сложить что ли?
>С чего это оно «идиотское»? Такое поведение — полезное и удобное.
Это не отменяет того факта что это высосанная из пальца хуйня и не имеет каких-то принципиальных преимуществ над говноконкатенацией. Получается, единствоенное, что тебе не нравится - то что они разные?
> Хорошо, даже если ты считаешь, что это понятие идиотское — тогда почему «JS» возвращает абсолютно бесполезную хуйню, вместо внятного «HuinyaException('Bbl nblmaemecb cgeJlamb xyuHl0')»
Я не вижу разницы между ексепшеном и непонятной хуйней, для меня и то и другое - неправильное поведение
VM546:1 Uncaught SyntaxError: Unexpected token ':' как бы намекает
>Это два множества кортежей: {(a,1)} и {(b,2)}, в результате его сложения будет {(a,1), (b,2)}.
Это можно интерпретировать только как кортежи? Что если я хочу что-то другое? Что если я вообще не хочу их складывать?
>А про Fast Fail слышал?
Это одна из философий обработки ошибок. В js другая. Что в этом плохого?
То, что она — говно. «Философия обработки ошибок JS» ошибки не обрабатывает, а заметает под коврик — чтобы через пару лет об них кто-нибудь споткнулся и ёбнулся.
js придумали для гостевух. На гостевухах такая политика оправдана
Ещё он дико удобен как браузерный калькулятор.
Ну вот и всё, с этим отступлением все противоречия разрешаются. Правда, остаются ещё сумасшедшие, которые пишут на «JS» проекты в сотни тысяч строк кода, но с ними уже должны врачи разбираться.
Только зачем-то полусохраняют обратную совместимость. Неясно, зачем в "JavaScript" и "C++"
* вводят новые фичи
* стараются поддерживать старое говно
* умудряются выпускать несовместимое говно со старыми версиями (например, убрали Function.prototype.caller)
* не вводят директивы явного отключения старого говна
В итоге язык с каждой новой версией начинает всё больше вонять, и на нём становится невозможно писать.
* Старый код больше не компилируется из-за мелких несовместимостей.
* Новый код использует новые фичи и хаки для обхода старых багов
Неясно, почему нельзя отключать говно директивами (вроде 'use strict') на постоянной основе
* Старый код продолжает работать без потери совместимости
* Новый код использует новый подход без старого говна
Видимо, боятся повторить эпический фейл питона.
> Неясно, почему нельзя отключать говно директивами (вроде 'use strict') на постоянной основе
Полагаю, что это будет слишком сложно для разработки: придётся по сути поддерживать два диалекта языка.
В итоге из-за выпиленного говна, которое слишком мешает одной группе экспертов языка, страдает 100500 групп с кодом, который его использует. И ещё 100500 групп, настрадавшихся от старого говна, не могут писать на нормальном языке.
Пусть лучше одна группа компиляторщиков пострадает за всех, но зато 100500 команд программистов будут спокойно работать.
Между поддержкой старого говна и выпиливанием старого говна нужен очень тонкий баланс. Уходим в одну сторону — получаем «WinAPI» с приветами из девяностых, уходим в другую — получаем «Python» и цирковое представление «переведи 100500 либ на третью версию».
Хотя бы 1% от них перевести в разработчики языка - и всё.
Тонкий баланс не нужен. Выпиливать старое просто нельзя, т.к. что-нибудь обязательно сломается.
Но в любом случае, даже если мы как-то ухитрились так сделать — всё равно в итоге получим десятки-сотни директив, что-то отключающих, включающих, меняющих, и каждое обновление языка 100500 программистов должны будут с ужасом во все свои проекты впиливать новые директивы, причём сначала им надо будет понять, какая из новых фич ломает проект.
Ещё остаются проблемы с API: к примеру, в одном из обновлений возьмут и выпилят из parseInt() второй аргумент. Получаем две версии стандартной библиотеки, между собой несовместимых. В следующем обновлении уберут тупую хуйню из forEach() — получаем три версии. Делаем оба изменения опциональными через директивы — получаем четыре версии. Обновляемся ещё пару раз — и выходим в окно, потому что поддерживать это будет попросту нереально.
Э, это не обратная совместимость.
Старый код должен работать как раньше, новый код должен использовать директивы для тех фич, которые ломают обратную совместимость.
В принципе, можно вообще ничего не менять по умолчанию, без директив не только не нарушать совместимость, но и новые фичи не включать. А дальше тупо в начале каждого файла будут писать что-то вида "use python 3.8".
Если получается кобенаторный рост, можно делать тупо директивы по версиям и генерацию адаптеров между версиями. Это максимум квадратичный рост. Но адаптеры можно писать только на одну версию назад, остальные генерировать и оптимизировать автоматически - линейный рост.
Стал лучше js после всех их «улучшений»?
Сомневаюсь.
Там где надежность чуть поменьше, но важна, это все тестируют до дыр и в тестировании действительно fail fast полезен
Там где js там обычно принципиально важной логики нет и я могу себе позволить отнять строку от строки потому что так быстрее чем лишние плюсы или конструкторы number писать
Наконец, это нечестно противопоставлять fail fast подходу js аргументируя "порчей данных"
Порча данных происходит много где и зачастую от ошибок логики программы а не какой-то js хуйни
Именно поэтому я как js разработчик храню деньги наличкой под подушкой
Там js точно до них не доберется
Где-то недавно читал, что когда у банков и ЖКХ-контор херится база, помогает чемодан с квитанциями.
Которые выцветают за пару месяцев.
Всё, нашёл доку 2, можешь убирать из багров.
> Как сложить {"a": 1} и {"b": 2} и произвольные два объекта - не понимаю.
И я тоже не понимаю. Но именно для этого и нужна консистентность: для тех объектов, для которых понятие суммы определено (математически или соображениями удобства), операция сложения должна возвращать их сумму. Для тех же, к которым такое понятие неприменимо, сама операция должна быть невалидна. В «Python» всё именно так.
> Это не отменяет того факта что это высосанная из пальца хуйня
Для тебя объединение списков — высосанная из пальца хуйня? А зачем тогда нужен «Array.prototype.concat»? Или ты считаешь, что «[1, 2, 3].concat([4, 5, 6])» выглядит проще, чем «[1, 2, 3] + [4, 5, 6]»?
> Я не вижу разницы между ексепшеном и непонятной хуйней, для меня и то и другое - неправильное поведение
Только эксепшон ты получишь сразу же, как только нажмёшь F5 (или что там жаваскриптеры жмут для деплоя). А непонятная хуйня может годами сидеть в системе, по-тихому портя данные клиентов.
>Для тебя объединение списков — высосанная из пальца хуйня? А зачем тогда нужен «Array.prototype.concat»? Или ты считаешь, что «[1, 2, 3].concat([4, 5, 6])» выглядит проще, чем «[1, 2, 3] + [4, 5, 6]»?
Вот я например хочу чтобы «[1, 2, 3] + [4, 5, 6]» было операцией сложения векторов. Что, это менее удобно? Менее логично? Менее что? С этой точки зрения, какое мне дело, вернет ли мне конкатенацию или какое-то говно?
>Только эксепшон ты получишь сразу же, как только нажмёшь F5 (или что там жаваскриптеры жмут для деплоя). А непонятная хуйня может годами сидеть в системе, по-тихому портя данные клиентов.
Это не говно, это просто другая модель
Да, ожидать от операции сложения списков поведения операции сложения векторов — это нелогично. Если нужно складывать вектора — складывай вектора:
> С этой точки зрения, какое мне дело, вернет ли мне конкатенацию или какое-то говно?
> Это не говно, это просто другая модель
Мы сошлись на том, что в языке для написания гостевух такая модель действительно может быть полезна.
Как будто что-то плохое
Ну ведь правда же не самое удобное решение. Сложение значение разных типов и чёткие правила автоматических преобразований типов - отличная фича, что бы там ни говорили сильнопитуизоиды. Но можно было бы выбрать значение для возврата и получше.
«undefined», например.
Кстати, мне оправдания в стиле «так написано в Книге» до боли напоминают беседы с крестовиками, которым показывают UB. Мол, сам дурак, что произвольные два инта складываешь, надо Стандарт читать!
Но, справедливости ради, если UB в си/крестах всё таки нужны для оптимизаций, то вот эти вот [1,2]+[3,4]=="1,23,4" — просто непродуманное говно.
Кстати и директивах. Почему бы не сделать safe-версию C/C++ с директивой 'use safe', где все UB заменили на какое-то логичное поведение, когда код либо как-то предсказуемо и медленно работает, либо вовсе не компилируется, если вместо UB нужно сгенерировать слишком сложный код (набор ситуаций описан в стандарте, либо включается флагами вида -Eall -Epedantic)?
На C/C++ пишут не только цари, которые каждое правило прочитали.
C++ - язык высокого уровня общего назначения. Тут можно выбирать высокоуроневые "медленные" виртуальные методы или использовать невиртуальное быстроговно уровнем пониже.
Зачем использовать Java/C# с друним синтаксисом, встроенной виртуальной машиной, автоматически инстанцированными шаблонами вместо C++, если дело касается какой-то мелочи - такой же язык, только с перламутровыми пуговицами?
У нас не хватает конструкторов. Так же и с техникой: либо ты выбираешь телефон с NFC и плохой прошивкой камеры, либо без NFC с хорошей прошивкой камеры, либо с плохим GPS модулем и кнопками, либо с хорошим GPS модулем и без кнопок, и нельзя взять сразу со всем хорошим потому, что каждый производитель делает свои велосипеды, продвигает отдельные фичи и не может сделать всё и сразу хорошо. В случае с языками нет такой явной прибыли при переманимании всех на свой язык, можно объединиться и внести разные фичи и модульную сборку в один язык или в одну платформу (как F#, C#, JScript.NET в .NET).
(Страуструп)
Насчёт высокоуровневости — спорный вопрос. Собственно, чёткого определения «уровневости» языка пока ещё не придумали и, боюсь, не придумают.
> Зачем использовать Java/C# с друним синтаксисом, встроенной виртуальной машиной, автоматически инстанцированными шаблонами вместо C++, если дело касается какой-то мелочи - такой же язык, только с перламутровыми пуговицами?
Какой мелочи? C++ изначально спроектирован с оглядкой на оптимизацию посредством UB (вернее, посредством предположения того, что UB в программе не будет). Убираем из него UB — получаем тормозящее говно (причём последнее — вовсе не от убирания UB). А зачем писать на тормозящем говне, если можно выбрать тормозящее не-говно: хоть «C#», хоть «Python», хоть «JavaScript»?
И нет, я ни в коем разе не оправдываю UB: это, конечно, говно. Но это говно приходится кушать за то, что конпелятор делает хелловорлды на крестах быстрыми.
Честно говоря, не понял концепцию языков-конструкторов. Вот, например, я хочу компиляцию в мышиные коды (чтоб быстро!), Вася хочет собрать прогу в бандл once и run её everywhere, а Пете надо хуярить скрипты под Unity. И что с этим делать — пилить по бэкенду на каждый возможный случай?
Почему бы и нет? Компиляторщики напилили 10 бэкэндов -
* 100000 проектов сэкономили на специалистах в других языках,
* 100000 проектов получили возможность перекомпилировать мышиные коды в run everywhere, когда мощности компьютеров повысились, а количество клиентов с устройствами нового типа увеличилось. Вкинуть 10000000 в разработку одного инструмента - дешевле, чем вкидывать 10000000000 в зарплаты программистов в 100000 проектах.
> получаем тормозящее говно
Ну и ладно.
> тормозящее не-говно
Надо учить. А если выучил тормозящее не-говно, но хочешь написать царский код, придётся заметно переучиваться. А так - включил компилятор в один режим - и он скомпилирует логичный, но медленный код; переключил в другой - и будут ошибки компиляции, исправив которые, можно получить быстрый код.
> переключил в другой - и будут ошибки компиляции, исправив которые, можно получить быстрый код.
Дык в том-то и дело, что отлавливать и выдавать по ошибке на все UB попросту нереально. Вот есть у нас какое-нибудь
— в крестах с запрещённым UB оно компилироваться не будет (это, кстати, одно из самых ебанутых UB).
Или вот так:
— тоже аж четыре потенциальных UB.
Любое обращение к укококозателю — парочка UB, любая операция с интом — UB, ссылка — UB, родился — UB, живёшь — UB, умер — UB.
По сути, компилятор с UB и компилятор без UB — это два совершенно разных продукта, пересекаться у них будут только парсеры. Впиливать функциональность одного во второй — только плодить баги и тратить ресурсы на поддержку. Разрабатывать отдельно — никому не нужно (кому нужен язык без UB — просто пишут на джавах).
Самый главный багор — это UB в переполнении интов. Чтобы от него избавиться — придётся каждую операцию с интами аккуратно заворачивать в обёрточки. Даже конпелятор с отсутствием оптимизаций на основе UB будет не так сильно тормозить.
Так уже есть WebAssembly и Emscripten.
Я давно говорил что js нужно не расширять всякой сахарозной питушней, но наоборот сужать.
Мне в asm.js нравится как они не никак не меняя язык фактически завезли в него явные 32-битные intы.
А вместо нечитаемого байт-кода как у CLR или JVM получился няшный js.
Серьезно, вы топите за эту хуйню только потому что где-то еще ее увидали. Она не имеет смысла сама по себе
Типа как умножению чисел обучили в школе, но если бы не обучили, оно бы не имело смысла, и можно было бы жить без него?
Ну или компьютеры. Увидали их люди и начали использовать, а сама по себе фигня "компьютер" не нужна, без неё жили 100500 лет?
Ничего само по себе не нужно, можно жить в мировом океане на этапе одноклеточных.
Как работает естественный отбор решений? Человек видит несколько вариантов решения проблемы и выбирает наиболее удобный. Когда появляется новый вариант, процесс выбора повторяется. Если человек ранее нигде не увидал новое решение, он его и и не выберет.
Чем [1,2,3] + [4,5,6] == '1,2,3,4,5,6' удобнее [1,2,3] + [4,5,6] == [1,2,3,4,5,6], если рассматривать потребности для средней программы?
Лично мне первый вариант пригождался чуть менее, чем никогда, а вот конкатенацию я регулярно использую.
Непонятно, какое отношение это имеет к теме разговора
>Чем [1,2,3] + [4,5,6] == '1,2,3,4,5,6' удобнее [1,2,3] + [4,5,6] == [1,2,3,4,5,6], если рассматривать потребности для средней программы?
Тем что, перефразируя Линуса Торвальдса, это мотивирует людей никогда и нигде не пользоваться этим говном.
Этот вопрос принципиален для js. Такое поведение допустимо для питона где можно переопределить оператор, затем привести новый тип и переопределить оператор для него. В случае невозможности переопределения операторов если "+" для структуры, которая задается списком, однозначно определить нельзя(я уже привел в пример что это можно считать векторной суммой), то намного лучше иметь совсем неиспользуемый результат и не поощрять чужеродные для языка практики
Кстати, а почему тогда «+» для строк их конкатенирует? Может, я хочу получить строку, в которой каждый символ — это сумма чаркодов соответствующих символов из исходных строк? Неоднозначность! Чужеродная практика!
А почему «*» работает не в кольце вычетов по модулю 42? Хочу кольцо вычетов! Неоднозначность! Чужеродная практика! Запретить!
А почему Array.prototype.concat() создаёт новый массив, вместо in-place конкатенирования? Хочу инплейс! Чужеродно!
В общем, такая логика крайне ущербна и глупа.
>Кстати, а почему тогда «+» для строк их конкатенирует? Может, я хочу получить строку, в которой каждый символ — это сумма чаркодов соответствующих символов из исходных строк? Неоднозначность! Чужеродная практика!
Совершенно верно. Для строк есть String.prototype.concat. Думаю, это просто издержка дизайна или фича для "фанатов удобства"
>А почему «*» работает не в кольце вычетов по модулю 42? Хочу кольцо вычетов! Неоднозначность! Чужеродная практика! Запретить!
>А почему Array.prototype.concat() создаёт новый массив, вместо in-place конкатенирования? Хочу инплейс! Чужеродно!
Да-да, очень интересно
Что мешало её определить?
> Никто не думал специально "а давайте строки конкатенируем"
Да-да, и именно поэтому «+» в жаваскрипте приводит оба аргумента к строкам и конкатенирует их. Ну, просто случайно так получилось.
> В таком контексте любые разговоры о пользе или логике лишены основания
Аргументируй, раз уж хочешь дискуссии.
Если какая-то часть языка бесполезна — значит, она лишняя. Следовательно, её необходимо либо сделать полезной ([1,2,3,4,5,6]), либо явно убрать (undefined/TypeError).
Отсутствие понятие "перегрузка оператора"
>Да-да, и именно поэтому «+» в жаваскрипте приводит оба аргумента к строкам и конкатенирует их. Ну, просто случайно так получилось.
Именно так. Операция приведения типа и конкатенация - отдельны, зоть и выполняются неявно
>Аргументируй, раз уж хочешь дискуссии.
>Если какая-то часть языка бесполезна — значит, она лишняя. Следовательно, её необходимо либо сделать полезной ([1,2,3,4,5,6]), либо явно убрать (undefined/TypeError).
Сложение массивов - это не часть языка по причине невозможности переопределить операторы
Как пользовательская перегрузка операторов связана с поведением оператора по умолчанию?
Почему тогда 1+2 == 3 в жс, если перегрузки + для интов там нет?
Array - не встроенный тип js, а потомок Object. В js невозможно определить оператор "+" для произвольного потомка встроенного типа. Рассказывать как охуенно можно определить "+" для Object надеюсь никто не хочет
>для произвольного потомка встроенного типа
Прототипы, не?
Почему тогда String([1,2,3]) === '1,2,3', а не '[object Object]'?
Array - не какой-то пользовательский тип, а встроенный в язык тип! Поведение для него может быть прописано отдельно без упоминания хуерархий классов. Более того, для того, чтобы он не тормозил, в обход абстракций жс ключи массива должны физически быть интами.
Потому что toString и valueOf это методы, которые можно переопредеелить, как и конструктор string
>Array - не какой-то пользовательский тип, а встроенный в язык тип!
Это неправда
>Поведение для него может быть прописано отдельно без упоминания хуерархий классов.
Как и для любого класса - наследника. в с# тоже все объекты - наследники object, но их поведение можно спокойно переопределить
>Более того, для того, чтобы он не тормозил, в обход абстракций жс ключи массива должны физически быть интами.
Детали реализации не имеют отношения к теме разговора.
>Это неправда
22.1 Array Objects
Array objects are exotic objects that give special treatment to a certain class of property names. See 9.4.2 for a definition
of this special treatment.
> Как и для любого класса - наследника. в с# тоже все объекты - наследники object, но их поведение можно спокойно переопределить
Так мы об этом и говорили: поведение + для массивов можно было спокойно переопределить.
of this special treatment.
Я не понимаю какое отношение это имеет к тому, что Array - это не встроенный тип, а наследник Object
>Так мы об этом и говорили: поведение + для массивов можно было спокойно переопределить.
Нет, нельзя было. В с# есть перегрузка операторов, в js - нет
Класс Array встроен в язык.
Не важно, он там проходит как наследник Object, или объявлен ещё одним "типом".
Ещё раз спрашиваю, причём здесь пользовательская перегрузка операторов? Чтобы определить поведение оператора для любых двух типов, отдельно упомянутых в стандарте, не нужно разрешать пользователю перегружать его. Для этого нужно определить определение оператора в стандарте языка для нужных типов.
Класс Array встроен в язык.
Не важно, он там проходит как наследник Object, или объявлен ещё одним "типом".
От этого он отдельным типом не становится.
>Чтобы определить поведение оператора для любых двух типов, не нужно разрешать пользователю перегружать его.
Конкретно для Array - нужно, так как это не тип
В общем случае - можно что угодно со стандартом сделать, непонятно правда, зачем
Не нужно, это даже я могу сделать. Берём параграф 12.8.3.1 и изменяем его (я его изменил, не надо этого искать в Стандарте!) вот таким образом:
Вуаля, теперь [1, 2, 3] + [4, 5, 6] == [1, 2, 3, 4, 5, 6].
Правда?
Создал, проверил.
В js есть "перегрузка операторов".
Допустим унарный плюс переопределяется на раз.
Что мешало его определить?
> Именно так. Операция приведения типа и конкатенация - отдельны, зоть и выполняются неявно
>> Никто не думал специально "а давайте строки конкатенируем".
Это предложение неверное. Эйх специально подумал о конкатенации строк. Операция «+» специально кастует оба аргумента в строку, а потом конкатенирует их. Это продуманная часть языка. И она — говно.
> Сложение массивов - это не часть языка по причине невозможности переопределить операторы
Мы обсуждаем дизайн языка, а именно то, что поведение плюса в JS — говно. Даже если Эйх не осилил перегрузку операторов, заставлять плюс приводить произвольные аргументы к строкам и конкатенировать их — идея откровенно идиотская, поскольку не приносит ровным счётом ничего полезного. Куда более адекватным поведением был бы возврат «undefined» для любых типов, для которых сложение не (может быть) определено.
Плохие практики прикрывают исключениями или объявляют UB.
Сделан плюс из желания помочь разработчику. Аналогично с '2'-1, чтобы программисту легче было взять число из формочки и применить к нему формулу. Просто не был продуман.
Есть в жс вещи вроде прототипов, которые сообщество оопитушков не понимает, есть двоякие '1'+1, которые иногда помогают, а иногда мешают, но питушня вроде []+[] - бесполезная с 99.999% случаях хрень, для которой в жизни есть альтернативы. Даже если бы было Object.prototype.toString = JSON.stringify;, уже плюс стал бы более полезным.
линк на параграф стандарта?
>Сделан плюс из желания помочь разработчику. Аналогично с '2'-1, чтобы программисту легче было взять число из формочки и применить к нему формулу. Просто не был продуман.
Это неправда. Во всех этих примерах первым и ключевым являются механики приведения типа. Приведение строки к числу и непосредственное вычитание - это разные операции которые необязательно были продуманы для работы вместе
>Есть в жс вещи вроде прототипов, которые сообщество оопитушков не понимает, есть двоякие '1'+1, которые иногда помогают, а иногда мешают, но питушня вроде []+[] - бесполезная с 99.999% случаях хрень, для которой в жизни есть альтернативы. Даже если бы было Object.prototype.toString = JSON.stringify;, уже плюс стал бы более полезным.
Не лепи вместе toString и "+"
12.8.3.1 Runtime Semantics: Evaluation
и далее по ссылкам
> Во всех этих примерах первым и ключевым являются механики приведения типа. Приведение строки к числу и непосредственное вычитание - это разные операции которые необязательно были продуманы для работы вместе
Для строк и чисел были продуманы, для массивов - не очень
> Не лепи вместе toString и "+"
Шта? В языке они уже слеплены.
>12.8.3.1 Runtime Semantics: Evaluation
>и далее по ссылкам
В параграфе не определена операция "+" для массивов
>Для строк и чисел были продуманы, для массивов - не очень
Это правда, но утверждение ни имеет никакого смысла
>Шта? В языке они уже слеплены.
Это тоже неправда. Приведение типов используется много где, "+" как бинарный оператор определен только для строк и чисел
В параграфе определена операция «+» для любых типов. Включая массив.
Это неправда. Параграф определяет механику приведения типов для дальнейшего сложения. Ничего о самой механике сложения не говорится
> Return the string-concatenation of lstr and rstr.
> Return the result of applying the addition operation to lnum and rnum.
Это я специально выделил. Или «возвратить результат конкатенации строк lstr и rstr» — это не «механика сложения»?
Да, все верно. Для примера, механика операции сложения определена в параграфе 12.8.5, механика конкатенации в стандарте не приведена. То что ты процитировал это все еще механика приведения типов
Правда штоле?
6.1.4
> То что ты процитировал это все еще механика приведения типов
Заканчивай толстить, это уже слишком жирно.
>Заканчивай толстить, это уже слишком жирно.
Напомню, что ты пытался мне набросить instanceof конструктора, так что уж точно не тебе меня учить как трактовать стандарт моего основного рабочего языка
Правильный вопрос.
Какая-то неправильная метаматика.
В js тоже можно переопределить оператор.
Array.prototype.toString = function(){return "123"}
>Его переопределить нельзя.
>Переопределение valueOf - это просто трюк, который к оператору не имеет никакого отношения
Н-н-нооо как же тогда изменяется результат его выполнения?
Если «не имеет никакого отношения».
Разве это не есть искомое Переопределение?
Во-вторых, определить сложение можно для чего угодно: достаточно написать в стандарте строчку «для объектов типа huj операция + возвращает объект типа cock».
Пункт 6.1 стандарта
>Во-вторых, определить сложение можно для чего угодно: достаточно написать в стандарте строчку «для объектов типа huj операция + возвращает объект типа cock».
Конечно можно. Только нахуя раздувать стандарт?
> Of the objects defined in this specification only Date objects (see 20.3.4.45) and Symbol objects (see 19.4.3.5) over-ride the default ToPrimitive behaviour. Date objects treat no hint as if the hint were String.
Date тоже не входит в святое множество типов из 6.1, но реализует кастомную питушню для ToPrimitive без какого-либо использования возможности задания этой кастомной питушни пользователем.
1. только метод, который используется внутри стандартной реализации ToPrimitive (сам ToPrimitive не меняется) и
2. результат ToPrimitive для не-объектов не может поменяться при определении, скажем, Number.prototype[Symbol.toPrimitive].
То есть пользователю ToPrimitive перегружать нельзя, а для Date смогли описать реализацию. С операторами то же самое. Пользователю явно перегружать не дают, есть возможность повлиять, авторы стандарта могут вписать кастомизацию для каких-угодно случаев.
"However, objects may over-ride this behaviour by defining a @@toPrimitive method."
Пользователю можно перегрузить ToPrimitive
> 6.1.5.1 Well-Known Symbols
> @@toPrimitive "Symbol.toPrimitive" A method that converts an object to a corresponding primitive value. Called by the ToPrimitive abstract operation
А в той сноске вообще написано, что определение @@toPrimitive может переопределить поведение "хинт - это число":
> When ToPrimitive is called with no hint, then it generally behaves as if the hint were Number. However, objects may over-ride this behaviour by defining a @@toPrimitive method.
@@toPrimitive - метод, ToPrimitive - абстрактная операция.
ToPrimitive вызывает @@toPrimitive, алгоритм ToPrimitive не меняется.
> When ToPrimitive is called with no hint, then it generally behaves as if the hint were Number. However, objects may over-ride this behaviour by defining a @@toPrimitive method. Of the objects defined in this specification only Date objects (see 20.3.4.45) and Symbol objects (see 19.4.3.5) over-ride the default ToPrimitive behaviour. Date objects treat no hint as if the hint were String.
В том же куске текста, который мы тут рассасываем, пишут, что они поведение самой ToPrimitive изменяют.
1. что valueOf, что @@toPrimitive работает только для Object
2. что определение valueOf, что @@toPrimitive влияет на выполнение какой-то другой операции.
Кстати, я бы заодно туда сравнение для Date ввёл.
>Кстати, я бы заодно туда сравнение для Date ввёл.
Оно же и так реализовано за счет приведения к unix timestamp
А вообще я за momentjs
Частично.
Если сравнивать через <, <=, >=, >, работает каст в число и unix timestamp.
Если сравнивать через ==, !=, работает поведение ==, != для Object со сравнением по ссылке, которое выдаст falsee у двух разных объектов с одинаковым unix timestamp.
Принимается.
> Конечно можно. Только нахуя раздувать стандарт?
А нахуя в стандарте такая неадекватная процедура сложения? Её можно переписать так, чтобы она, во-первых, была существенно короче и проще, а во-вторых — более адекватной. Как-нибудь вот так:
Я согласен с тем что это хуйня. Но изменить что-то уже вряд ли можно из-за обратной совместимости
можно сделать 'use stricter'
ещё останется 'use strictest' для случая, если 'use stricter' не всё говно запретит
Почему вдруг невозможно описать в стандарте поведение сложения для массива? Религия не позволяет?
>Почему вдруг невозможно описать в стандарте поведение сложения для массива? Религия не позволяет?
Именно так. Лично я считаю что нахуй не надо
Вот только надо трогать святой void грязными лапами.
Это практически единственная инвариантная вещь жса.
Которая спасает от
var undefined=42;
fixed.
> А непонятная хуйня может годами сидеть в системе, по-тихому портя данные клиентов.
Сразу же, как только нажмёшь F5 и воспроизведёшь хитрожопую ситуацию, в которой возникает исключение.
Как-то раз Пи уже показывал, что JS прекрасен как конструктор языков.
Осталось только написать фреймворки высокого уровня, которые перехреначивают прототипы и делают для JS поведение
* со строгой питуизацией как в python
* со слабой типизацией и полезными результатами как в python
* с кучей математических фич как в Matlab
+1
Ну разве что для редких тестов использовать.
Э, "обратная операция" - это совсем другое. Корень и степень - взаимно обратные операции на R+. А typeof и instanceof - как sin и cos - две стороны одной медали.
Однако, typeof null === 'object' - старое говно, которое давно пора было бы убрать хотя бы в strict mode.
Вот Борманд более логичное написал про new.
> ты скажешь, что typeof не обязана быть обратной от instanceof
Даже если считать, что 'number' === Number. Или вовсе считать, что Number === 1 === 2 === ...,
Где хоть что-то намекающее на обратность?
Неождианное поведение это всегда изьян.
На самом деле этого точно не знает никто.
Допуск должен быть пропорционален абсолютному значению аргумента. Только какого: большего или меньшего или их среднему значению?
Когда аргумент близок к нулю, дальше уменьшать допуск дальше мы не можем, иначе можем получить неадекватный результат. Значит, нужно ограничить минимальное значение допуска.
На следующем шаге получим что-то типа такого:
Ничего не забыл или алгоритм нужно ещё доработать?
Я бы этой антицарской и тормозной хуйнёй не занимался.
А просто бы вычел их как целые и наложил бы маску на нижние биты.
Фууууу. Ну питушня же анскилозная. Какое УМНОЖЕНИЕ )))
Выделенные жырным нули и есть ворецируемый эпсилон.
Если они разные, придётся мантиссу одного из чисел сдвигать.
Если числа отличаются НА ПОРЯДОК, то эпсилон уже не нужен.
>Если они разные
То и числа разные :)
Рабоать она не будет работать с числами разного знака около нуля и NaNaми.
Но это легко поправить 2-3 доп. условиями
Такой же пример можно придумать и для двоичных порядков.
Вычитание вынесет 1 бит разницы в порядках в младшие разряды.
А там её схавает битовая маска.
В противном случае разница между числами слишком велика.
#скрыльник, #напитуль, #хрюльни, #вроверь
Ещё раз: вычитаются мантиссы И порядки. Как одно число.
В этом заключается царское изящество данного способа.
Причём он работает независимо от порядка чисел.
https://ideone.com/wTnBMz
Казалось бы, абсолютная разница числе составляет ЦЕЛУЮ единицу.
Однако вычитание нивелирует её в младшие разряды.
Между 4.0000000001 и 3.9999999999 разность равна 2E-10. Это довольно маленькое число.
Однако, в шестнадцатеричном представлении
4.0000000001 = 0x1.000000001b7ce000p+2
3.9999999999 = 0x1.ffffffffc9064000p+1
Поскольку IEEE754 для нормализованных чисел не хранит ведущую единицу, мантиссы будут храниться как 0x000000001b7ce и 0xffffffffc9064 соответственно (т. е. как совершенно непохожие числа), а порядки будут отличаться на единицу.
Тогда:
4.0000000001 = 0x2.0000000036f9cp+1
3.9999999999 = 0x1.ffffffffc9064000p+1
Или:
4.0000000001 = 0x1.000000001b7cep+2
3.9999999999 = 0x0.ffffffffe4832p+2
Мантиссы 2.0000000036f9 и 1.ffffffffc9064000 либо 1.000000001b7ce и 0.ffffffffe4832 уже́ можно сравнивать.
Ну правильно
И мантиссы как раз отличаются на 1.
Но разница уходит в младшие разряды. И получается довольно несущественной.
https://ideone.com/kdVR1u
Для даблов, с их точностью 2.00e-010 это довольно большая мантисса.
Потому я взял 1e-013.
Впрочем можно просто увеличить число нулей в 0x7FFFFFFFFFFFF000L
В этом весь смысл хака.
Вычитать и порядки ВМЕСТЕ с мантиссами. Как единое целое.
Тут ещё большой вопрос что каждый понимает под «эквивалентностью».
Лично мне кажется два флоата эквивалентны, если их битовые представления эквивалентны *.
>bool operator ==
А это я бы обозначил как «приблизительное равенство».
* А NaNы сведены к одному фиксированному значению.
А ещё у плавпитуха бывают денормализованные числа. Когда порядок слишком маленький (иногда это называют underflow в противоположность overflow), включается второй формат битового представления: в мантиссе больше не подразумевается ведущая единица. Я не помню, пересекаются ли множества нормализованных и денормализованных (нужно проверять). Если вдруг они пересекаются, то нормализованное и денормализованное представление одного и того же числа будем считать разными числами?
>+0 и -0 будем считать разными числами?
Я бы не сказал что они разные. Но они явно неэквивалентные.
Текстовое представление ведь различается.
>нормализованное и денормализованное представление одного и того же числа будем считать разными числами?
См. начало ветки:
http://govnokod.ru/26263#comment516271
«на самом деле этого точно не знает никто»
Кресты для быдла
https://www.php.net/manual/en/reserved.constants.php
Именно поэтому я за «PHP».
Чтобы флоат циклы по целым числам не ломались.
В более общем случае если y > 0, z > y*PHP_FLOAT_EPSILON, то y + z > y.
Всё, больше ничего оно не гарантирует.
В «PHP» нет гарантий, что 0.3 + 0.7 === 1.0.
В «PHP» нет гарантий, что 100000.0 + 500.0 === 100500.0.
Ещё забыли про
typeof null
0.1 + 0.2
Все ссылки ведут на какой-то говносайт, который у меня нет открывается, так что да, на дваче
персона Альц-геймер
В остальном это лишь говно программирования, в котором привыкли купаться сраные сишники.
Вот увидите, когда выйдут ЯПы нового поколения, старые жсники будут топить за typeof null === 'object', [1]+[1] = '1,2' и прочее логичное говно как сейчас сишники объясняют, что 0.1 + 0.2 != 0.3 - логично только потому, что прошло достаточно много времени с того момента, как эта "фича" была добавлена в плавающего питуха.
Сейчас только время возникновения разделяет 0.1 + 0.2 != 0.3 и [1]+[1] = '1,2'. К 0.1 + 0.2 != 0.3 все давно привыкли, а [1]+[1] = '1,2' - всё ещё новое. Но фактически всё это - говно.
И если числа реализовали через задницу, то 0.1 + 0.2 != 0.3 для адекватного человека никогда не станет логичным.
Ну да, не додумались завезти рациональные числа из коробки в жопулярные промышленные языки.
Теперь все ловят багры плавающих питухов.
Причём на момент создания жаб,пнп,жсов (1995) дроби могли оказаться шустрее, чем эмулируемые флоаты или тормознутые инструкции x87-копроцессора.
ЕМНИП FPU стал обязательным только в Пентиумах. А в 486 он мало того что был опциональным, так ещё и тупил безбожно.
Но даже Пентиумы не были панацеей, вспомним FDIV-bug, связанный опять-таки с плавающим питухом.
Сама реальность должна была подсказать разрабам, что флоаты говно.
UBASIC version 8 has the high-precision real and complex arithmetic (up to 2600 digits) of prior versions, and adds exact rational arithmetic and arithmetic of single-variable polynomials with complex, rational, or modulo p coefficients, as well as string handling and limited list handling abilities.
https://en.wikipedia.org/wiki/UBASIC
ftp://ftp.bu.edu/mirrors/simtelnet/msdos/ubasic/
Многие платформы на тот момент если и поддерживали плавающего питуха, то только благодаря необязательному копроцессору.
К примеру Моторолла и в 1995 году выпускала недорогие модели процессоров без FPU.
Таков был общий тренд. Интел здесь не исключение. Наоборот, штеуд был одним из пионеров, кто интегрировал FPU и CPU в одном чипе.
Нужно просто всё складывать с плюсами.
Малость WTF. Много NaN.
>[1]+[1] = '1,2' - всё ещё новое.
All external data is stored and referenced from a single object, called the heap. Essentially this heap is a massive array (intended to be a typed array, which is highly optimized for performance).
All data is stored within this array – effectively replacing global variables, data structures, closures, and any other forms of data storage.
Posted: April 3rd, 2013
https://johnresig.com/blog/asmjs-javascript-compile-target/
Царь мудро учил неразумных анскилябр, что массив — единственно полезная структура.
Все остальные формы данных — есть частный случай массива.
Глупые анскилябры только кукарекали и насмехались над Царём.
А теперь уже более 90% популярных сайтов используют данную технологию.
Ну кстати был микроконтроллер однобитный.