Pull to refresh

Comments 353

Баян. Скучно. Придирки к стилю – тупо. Перевод отстой:
'0', 0 и 0.0 являются неправильными, но '0.0' — правильным.
А имеется в виду допустимость этих конструкций или то, как они приводятся к булевским переменным? Не зная джавы, я не понимаю, о чём речь.
как они приводятся к булевским переменным

А, так вот что это значило. В таком виде эта строка обретает смысл :)

При чём здесь java? Это про js.

Причем тут js? Это в разделе про PHP.

Ок, но это точно не про java, которая упомянута в комментарии, на который я отвечал.

Ну нахер! Пошёл доучивать английский, чтобы больше не видеть эти волшебные переводы от надмозгов, научившихся пользоваться PROMT'ом в перерывам между охлаждением трахания и рассматриванием пользы с Углепластиком.
Всё ещё хуже:
Оператор === устраняет эту проблему при неприведении типов данных, но вводит в заблуждение, будучи происходящим из других языков.

должно быть "… вводит в заблуждение приходящих из других языков" (программистов).

чтобы ваше основание логарифма было 10:

«основание системы счисления» — на этом я перестал читать перевод.
Как мне теперь на C# писать с такими чудовищными недостатками? Я ведь так хотел получить исключение в рантайме, просуммировав два объекта, в классах которых не определён оператор сложения.
Кстати говоря, со сложением не все так однозначно. Если складывать dynamic, то все будет работать:
T Plus<T>(T t1, T t2)
{
    return (dynamic)t1 + (dynamic)t2;
}

Ну так dynamic как бы и намекает что все проверки будут в рантайме, в этом его соль.


А вообще да, если хочется то через динамик всегда можно.


Даже мультиметоды (двойную диспечиризацию) можно сделать.

Для меня это большая боль — операторы и методы generic'ов. Если бы все int, float и т.п. были бы каким-нибудь Numerable (да, я знаю, что структуры не наследуются), чтобы использовать where, все было бы чуточку проще
Если для вас это действительно важно и это не просто «хотелка», то можно сделать метод не параметризованным, а работающим, например, с double и уже результат его работы приводить к тому или иному численному типу с нужными допущениями (округления, отсечение дробной части).
Можете так же посмотреть на Scala, если у вас есть выбор. Там у операторов нет привелегированного положения и они являются обычными методами, что позволит сделать generic-метод с нужными constraints.
Скорее просто хотелка.

Там у операторов нет привелегированного положения и они являются обычными методами, что позволит сделать generic-метод с нужными constraints.


Операторы в C# — обычные методы operatorX. Параметр generic-метода без всяких constraints имеет методы Object (ToString, Equal, GetHashCode итп). Сравнения, операции, другие методы — все надо делать через constraints определенного интерфейса. Например, сравнение — IComparable. Но интерфейса для математических операций нет. Да и примитивные типы являются по-сути структурами, а не классами, поэтому даже IComparable тут не канает.

P.S. Случайно узнал, что Array.Sort как-то работает даже с T[] без всяких ограничений.
Не решает: не всякая структура — число.
Максимум, вы можете написать where T: struct, IComparable, но кроме чисел в ограничение впишется и любая другая структура (не число) с заданным интерфейсом.

Можно еще IConvertible дописать. Просто потому что это более редкий интерфейс, нежели IComparable.

А я считаю отличный справочник для начинающих троллей. Можно легко начать языковый срач по любому языку из списка. А если серьезно в принципе проделана хорошая работа. Такой общий взгляд как раз показывает, что идеальных языков нет, и они порой имеют похожие болячки. А также поможет не сформировавшим свое мнение особам перестать перебегать с одного языка на другой надеясь что вот следующий язык уж точно будет лучше.
Да нихрена этот «общий взгляд» не показывает. Возьмите мои любимые .NET и C# – из обоснованных претензий там только IDisposable да property override. А реальные проблемы, вроде бардака в коллекциях, идиотского System.Enum, неудобных делегатов (broken by design!), бредового доступа к памяти и массивам (планируется улучшить в виде Memory Span API), отсутствие tagged union (частично исправлено в C# 7) и др., не упомянуты.
UFO just landed and posted this here
Честно говоря тоже не понял претензий к системе типов. Она непонятная и странная только для людей далеких от математики, но так такие вообще с ФП не очень дружат. И при этом ни слова о сообщениях об ошибках — вот это была боль на самом деле, да. Правда я не занимался хаскелем уже пару лет, может что-то и поменяли к лучшему.
UFO just landed and posted this here

Да там даже IDisposable не в тему. Давно же уже договорились, что при правильной архитектуре полный Disposable-паттерн не нужен.


Если класс непосредственно владеет только управляемыми ресурсами — достаточно простой реализации интерфейса. А если он владеет неуправляемым ресурсом — его надо наследовать от SafeHandle. Любая другая реализация может привести к утечкам памяти при выгрузке домена приложения.

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

А в чем проблема вовремя отписаться от управляемого ресурса? Для этого не нужны финализатор и полный Disposable-паттерн.

Пардоньте, невнимательно прочитал в первый раз. Претензий больше не имею.
Сколько использую C#, первый раз слышу про некоторые вещи, можете пояснить?

неудобных делегатов (broken by design!)

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

бредового доступа к памяти и массивам (планируется улучшить в виде Memory Span API)

А вот это сильно интересно. В чем бред?
Делегаты – это просто класс с конструктортом и некоторыми методами, который генерируется компилятором и заменяется на специальный код в рантайме средой исполнения. У делегата есть контекст – это ссылка на объект, которая поставляется как первый аргумент методу. За исключением случая, когда контекст равен null, тогда через рефлексию выясняется, как вызывать метод, поэтому делегаты такие медленные. У делегатов может быть не одна пара контекст-метод, а несколько. Делегат без таких пар превращается в null. У делегатов нет структурной эквивалентности и наследования друг от друга, т.е. EventHandler и Action<object, EventArgs> это совершенно разные вещи. Короче говоря, лучше чем в Java, но хак на хаке и могло быть гораздо удобнее.

Про доступ к памяти я могу писать бесконечно. Например, почему нет read-only array? Почему String и char[] это разные вещи с разными API? Почему разые API используют массивы, строки, указатели, IntPtr, что угодно из предыдущего плюс start index и length, иногда даже IEnumerable, но не единый способ доступа к памяти? Почему существует ArraySegment, но он нигде не используется? Почему я не могу превратить часть строки в число и обратно без миллиона аллокаций? Почему есть OffsetToStringData, но нет аналога для массивов? (Ответ: потому что массивы это один большой «особый случай» для среды исполнения и языков.) И я ещё не начинал про SZArray! Это всё начинают исправлять с внедрением Memory Span API. Надеюсь они доведут дело до конца и переделают большинство стандартной библиотеки на нормальные аргументы.

String и char[] — это разные вещи потому что первый неизменяем. А StringBuilder и char[] — это ращные вещи потому что у первого переменная длина. Часть строки превращается в число и обратно при помощи всего одной аллокации, а не миллиона.

Почему String и char[] это разные вещи с разными API?


Потому что строки — иммутабельные объекты (поэтому нет методов работы как IEnumerable) и имеют (внезапно) своим методы по работе со строками (не C все-таки).

С остальным в принципе соглашусь, но в 95% случаев (на вскидку) используются различные реализации IEnumerable, а точнее — массивы и System.Collections.Generic

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

И сломают кучу-кучу-кучу-кучу существующего кода?
(Вы уж не думаете, что я этого не знаю?)

Проблема в том, что различные API требуют char[] или string, хотя им нужно гораздо меньший контракт, чем предоставляют char[] или string. Они вынуждены поддерживать оба класса, потому что для потребления они эквивалентны (даже имеют бинарную совместимость), но типа с подходящим контрактом попросту не существует.

Возьмите конструктор строки: вам на самом деле требуется всего лишь указатель, длина, кодировка для создания строки, а не 8 оверлоадов. Это всё можно схлопнуть в два-три варианта конструктора с ReadOnlySpan.

Возьмите TextElementEnumerator, он оперирует исключительно на строках, делая огромное количество аллокаций, хотя единственный контракт, требуемый ему от типа string – это неизменяемость. ReadOnlySpan избавит вас от мучений.

В 99% случаев, когда используется массив в качестве аргумента, тип массива не подходит. Возьмите класс Array – все методы, кроме Clear, SetValue, Reverse, Sort, не должны принимать массивы в качестве аргументов. И опять ReadOnlySpan спасет.

А ещё поддержку UTF-8 строк мешает сделать именно вот такой изначально плохой подход к работе с памятью. Основной вариант сейчас это распознавание отдельных опкодов в существующих программах и изменение их для более корректной работы с памятью.
Проблема в том, что различные API требуют char[] или string, хотя им нужно гораздо меньший контракт, чем предоставляют char[] или string.

Куда уж меньше char[] ?

ReadOnlySpan.

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

Как выбирают
Javascript: И фронт и бек на одном языке, ну наконец то.
PHP: В моем городнейм 120 вакансий ит, 110 по php, без хлеба с маслом не останусь.
Java: СМАРТФОНЫ = ANDROID! ANDROID = СМАРТФОНЫ!
Obj-C: Я что зря накопил на макбук и айфон.
С++: ОБОЖАЮ ИГРЫ. Отправил резюме в еа, убисофт, и т.д.
C#: Прикинув силы реально, попробую на Unity.
С: Я использую Линукс, или как я недавно начал говорить Гну слэш Линукс.

Как не выбирают язык
pony() + (!((f{}=try(a(a+b==(!x.magic%n)))/(/friend/*)::bool(1)))) // Вот так не работает, а ведь должно!
Замечательные примеры!

По основной статье — справедливости ради отсюда бы поубирать придирки к стилям именования а также болячки ранних версий языков. У того же Руби в 2 раза тогда сократится список «болячек». На самом деле, какая разница что было в 2007-м с языком, если сейчас в том же 2.3.1 большая часть претензий уже не актуальная. Что касается придирок по upcase и downcase — вообще вкусовщина странная. Если уж так нужно, руби позволяет применять манки-патчинг к кор-методам и классам, так что при желании за пару строк можете себе сделать хоть метод toUpperCaseForMePlease и это будет работать. А если совсем тяжелый случай — оформляете эти горе-методы в свою либу (тоже всего несколько строк) и инклудите в свои проекты (главное чтобы на гитхабе не увидел никто). В свое время поступал так с округлениями при переходе с 1.9 на 2.0, писал манки-патч умещающийся в один 6-ти-строчный гист.
Очень много вкусовщины, причём необоснованной. CamelCase — отстой? Ну ок, а какие ваши аргументы? И на этом начинающий тролль всё.
И много фактических ошибок. Мелких, но показывающих поверхностное знание предмета.
Например: «любой php код, даже не генерирующий html, должен быть заключен в <?php… ?> » — закрывающая скобка мало того, что необязательна, так ещё и обоснованно считается довольно серьёзной ошибкой.
С CamelCase, я так понял, претензия к сложным именованиям — XMLHttpRequest (я бы написал XmlHttpRequest, например) и HTMLHRElement (ну тут действительно волшебно — HTML HR и Element сливаются… не айс… лучше бы было бы HtmlHrElement)
это потому что твой язык — отстой, ты говоришь что идеальных языков нет? :-\
isNaN(x) — хоть и преведено как «правильный способ тестирования» на самом деле таковым не является. Проверяет не на то является ли данный объект NaN а на то получится ли из этого объекта NaN при приведении к числу

для примера

    isNaN('asd')  //вернёт true, хотя 'asd' это строка а не NaN
    Number.isNaN('asd') //вернёт false, что на мой взгляд более верно
Все верно.
isNaN(s) проверяет является ли s «не числом» явно или не явно (в виде строки)
Number.isNaN(s) проверяет является ли s именно значением NaN
Обе функции дают правильный результат, но смысл у них немного разный.
Я знаю как работают эти функции, именно поэтому я написал этот код. Просто функции isSomething обычно возвращают true если переданный аргумент является этим Something. Строка NaN-ом не является. Строка это строка.
Все началось с шутки в которой была лишь доля шутки. Не хочу дальше спорить.
Да я то даже и не спорю, просто isNaN считается примером нехорошей части javascript, т.к. делает не то, как называется
«NaN» это «Not a Number».
Выражение if isNaN(a) соответствует «если a не число», что логично, на мой взгляд.
Значит вы просто не знакомы с IEEE754
Это очень плохая практика, называть что-то так, что это можно трактовать несколькими способами. Все должно быть однозначно. Термин NaN — из IEEE754. И не надо ему придавать других значений.
Ваша задача не соблюсти формальность, а сделать так, чтобы программист, использующий вашу библиотеку не ошибся по той или иной причине. Ваши оправдания никак этой цели не соответствуют.
Более того, не рекомендуется использовать отрицание в названии функции. Лучше сделать функцию isNumber().
Вот чтобы такой ерунды не возникало, и нужна строгая типизация.

Может, это правильно, когда при попытке вызова isNan(string) язык возвращает не true и не false, а exception?

NaN в данном контексте ни разу не отрицание, это просто название специального значения. Для isNumber было бы ожидаемо давать ответ на вопрос «тип аргумента — число?» и isNumber(NaN), соответственно, должно выдавать true: NaN в системе типов это число.

Почитайте выше: https://habrahabr.ru/post/315152/#comment_9914104
В данном контексте это как раз не «специальное значение NaN». Оттого и спор.

Даже в данном контексте это «специальное значение». isNaN(x) — это как Number.isNaN(+x), Number.isNaN(x) — это typeof x === 'number' && isNaN(x). Что‐то вроде предложенного ниже convertsToNaN было бы, конечно, более однозначным названием, но это всё ещё проверка на то, не является ли x специальным значением, хотя и в контексте, в котором x будет приведено к числу. Никакого отрицания тут нет, потому что NaN — тоже число согласно системе типов. Отрицание было бы, если бы при приведении генерировалась ошибка, и тогда название isNaN было бы весьма странным.

Просто когда наша переменная NaN мы ничего сделать не можем, кроме как залогать ошибку\бросить exception, а когда это строка не приводимая к числу — вполне может быть что там что-нибудь внятное, просто необработанное. И вот тут то из-за неоднозначного названия может закрасться логическая ошибка.

С тем, что названию лучше бы быть другим я согласен. Но с тем, что «другим» значит !isNumber — нет, равно как и с тем, что в названии isNaN есть отрицание. В частности, convertsToNaN было бы адекватнее, но, вообще‐то, пока унарный плюс не бросает исключений (кстати, а он при каких‐то условиях бросает, при которых isNaN — нет?), ни isNaN, ни convertsToNaN не нужны при наличии Number.isNaN.

Да, просто нужно знать про Number.isNaN, который кошерен. И понимать что он отличается от isNaN. Не читавшему доки может быть открытием.
if isNan(a) на мой взгляд должно означать что a это NaN
тогда функция должна называться convertsToNaN, или как-нибудь ещё, но is подчёркивает что переменная в данный момент является NaN
Так isNaN принимает на вход число, а дальше в силу вступает неявное приведение типов. Сама функция тут ни при чём, иначе все функции в JS придётся называть «convertXX».
javascript же не строготипизированный, так что isNaN принимает переменную, и независимо от типа переменной должен вести себя правильно. Тоесть если пришло не число — нужно возвращать false, т.к. typeof NaN === «number»
Он ведёт себя правильно, вас же 10+true === 11 не смущает?
В JS вообще функции в первую очередь реализуются с неявным приведением (==, и только потом ===), а большинство и вообще не имеет аналогов без приведения. «false».endsWith(false) === true.
Должна ли функция isString приводить к строке входящий параметр?
Если бы проблемы о которой я говорю не существовало — не появился бы «правильный» Number.isNaN
Ну, эти «is» методы Number — это просто аналоги обычных с проверкой типа.
Так же и isFinite(«123») === true, a Number.isFinite(«123») === false.
Называть это проблемой — преувеличение. И эти пара добавленных функций — просто сахар, избавляющий от проверки типа, если(!) для вас важно выделять именно NaN, который в вашем коде каким-то образом может приходить вперемежку со строками.
typeof(a) === "number" && isNaN(a)

против
Number.isNaN(a)
Судя по названию, она должна проверять тип, а не значение, как делает isNaN.
Вы же не с (тоже предполагаемой) функцией „isNumber“ сравниваете.
Хотите проверять без приведения? Пишете x!=x, экономите четыре символа.
Эка подрывает, по Go не правда, есть константы
Какой-то слабый троллинг, очень слабый троллинг!..
Есть попытка, но не окончательно

Не сразу понял, что речь о try и finally.

А как вам понравилось «Обязательным является свой аргумент в методах»? (Речь об аргументе self)
Очень долго пытался понять, по каким признакам аргумент становится «своим». Потом дошло, о чем речь

Короче сразу минус такому переводу. Непонятно, кто переводил и знает ли вообще переводчик о чём речь в тексте.

Обязательным является свой аргумент в методах

Тоже хорошо. Где-то был self.

А я вообще, пока не прочитал Ваш комментарий, не понял о чём речь.
«Она со мной, углепластик. Охладите траханье»
Попробуйте с закрывающей скобочкой.
https://goo.gl/5qAzXE

В любом случае, получилось очень колко.
в адрес нужно добавить закрывающую скобку
Delphi — это отдельный диалект Object Pascal'я.
Как юнити — это отдельный диалект C#?

Как Оберон — отдельный диалект Object Pascal.

Оберон намного сильнее отличается от Паскаля, нежели Delphi.

Но наверняка Delphi отличается от Паскаля намного сильнее, чем C# от C# :)

Но не сильнее чем C# от Visual Studio!

С# всё-таки язык программирования, а Visual Studio — среда разработки. А Delphi c Pascal оба — языки программирования.


Эдак можно договорориться до того, что С# от Ворда отличается сильнее, чем Delphi от Pascal :). И, что характерно, утверждение будет верное :)

C# от ворда — сильно, но вот Visual Basic… С чем бы мы его не сравнивали, получается боль…
А что не так с visual basic? Полная копия C# — просто синтаксис на другой лад. И компилируется в один и тот же код.
Среда, которая чаще всего используется. Программировать дефолтным редактором офиса…
Допускаю, ибо дело было ещё в школе. И с тех пор редактор в офисе не изменился.

А зачем ему меняться, если он как раньше VBA редактировал, так и сейчас?


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

Что значит отдельным? Почитайте про то как работает .NETи как все .NET языки «отличаются».

При чем тут вообще .NET? VB.NET — это третий язык, отличающийся как от VB, так и от VBA

Это всё MS виновата… переиспользуют названия, а потом приходится новичкам по 10 раз рассказывать чем отличается VB от VB.NET, ASP от ASP.NET, ASP.NET от ASP.NET MVC и т.д.

Спасибо, не знал о чистом VB.
Начиная с Delphi7 (2002 год) Борландцы назвали Delphi самостоятельным языком, основанным на Object Pascal.
Странно утверждать такие вещи, не разбираясь в вопросе.
UFO just landed and posted this here
Судя по тому, что Swift обошли стороной, мой язык, всё-таки, не отстой.
Нужен последний пункт для остальных языков:

«А твой любимый язык настолько отстой, что о нем даже писать неохота, это очевидно!»
Во-во-воу! Не трогай BrainFuck, он охуенен!

Судя по


Несовместимость браузеров Firefox, Internet Explorer, Opera, Google Chrome, Safari, Konqueror и т.д. делает работу с DOM чрезвычайно трудным делом.

статья писалась тогда, когда Swift ещё не было или он только-только появился.

UFO just landed and posted this here

Если перейти на оригинал, то видно что это — страница какого-то вики-проекта. Разные части вполне могли быть написаны в разное время.

UFO just landed and posted this here

Имеется ввиду, что в браузерах разное API для работы с DOM.

UFO just landed and posted this here
Упоминание о Swift в статье всё-таки есть (в разделе про ObjC).
UFO just landed and posted this here
А я знаю кобол, его в списке нет, кобол — не отстой.
UFO just landed and posted this here

Это о Array и Map, видимо.

Сквозь этот бред прослеживается боль в отсутствии синтаксического сахара для доступа к элементам Map или Collection.
Ага, там речь про literal constants.
Лично меня, если честно, бесят вот эти модификаторы перед каждым объявлением — «public», «final» или там «static». Я понимаю, зачем они. Просто после c#, где как-то без этого можно обойтись, не потеряв в функционале, глаза немного кровоточат: конкретно код занимает места столько же, сколько декларации классов и их членов…

Да ну? В C# отличается разве что область видимости по умолчанию для членов классов — закрытая вместо внутренней. И внутренних классов (в понимании Java) нет.


В остальном — все также надо расставлять модификаторы.

Или вы про final перед параметрами? Так они и в Java не обязательны...

UFO just landed and posted this here
Не очень понял каким вообще боком CSS относится к "языкам программирования", но именно раздел с CSS выглядит как жалобы типичного неосилятора.
Ты не поверишь. Там все разделы так выглядят.
У Rust есть исключения.

Ну вот, только на ЛОРе закончился срач. :) Нет в Rust исключений. Исключение это механизм сообщения об ошибке, который выкидывает управление из функции по стеку до ближайшего обработчика. Исключение не трогает объекты программы и предоставляет обработчику решать что делать дальше. Паника же — средство контролируемого уничтожения потока, в котором она произошла. Паника вызывает деструкторы. И то, что её можно перехватить и некоторым шаманизмом сохранить поток не делает её исключением. Объекты всё равно придётся создать заново.

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

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

Две реализации случайных чисел — math/rand и crypto/rand

Забавно. В основном все прочитал мельком, а за это прям глаз зацепился. Прям выбивается из всей этой вкусовщины и вбросов.

Да ни чем оно не выбивается. Такая же глупость как все остальное. Подобное разделение есть в любом озяке общего назначения.

Остальные вещи, по крайней мере, еще как-то субъективны. А это похоже вставлено чисто из-за глупости. Знать, что такое RNG вообще, и не понимать, зачем они разные нужны.

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

К слову, нет, не одобряю. Напротив, удивился, что кто-то настолько невежственен, что упомянул такую заковыристую вещь как RNG и осмелился упрекнуть в том, что есть две реализации. Первый раз вообще вижу подобный упрек.
UFO just landed and posted this here

Что это за высер промпта из начала 2000-х?


ничто, кроме GCC и шумихи,

Убило наповал

Напомнило: http://harmful.cat-v.org/software/operating-systems/os-suck
Прочитал список. Поразительно, но RT11 не сосёт. Все на PDP-11/УКНЦ! :)
Про Javascript практически каждый недостаток заканчивается тем, что в «ES6 уже исправлено». Только сегодня практически все пишут на ES6, а кто не пишет — очень рекомендую, или сразу на Typescript
Остаётся один язык — brainfuck. Он не отстой. На нём девелопить будем.

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


Также:


Язык С

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

Это вранье. Все статические объекты в С инициализируются нулями по умолчанию.


Язык С++

Он имеет обратную совместимость с С.

Нет.


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

Различия С и С++ — огромны и фундаментальны. С — lvalue-discarding language, C++ — lvalue-preserving language. Уже этого достаточно для того, чтобы заявлять, что любые сходства между этими языками — не глубже уровня сходного синтаксиса.


Вызов std::string::c_str() требуется для преобразования std::string в char*. Из самого мощного языка мы всегда имели бы полностью принимаемый перегруженный operator const char* () const.

Косноязычие не позволяет понять, что именно имеется в виду.


Разработчикам, возможно, придётся побеспокоиться о вопросах оптимизации, таких как, например, объявлять функцию inline (встраиваемой) или нет; но после принятия такого решения оно является только предложением: компилятор может решить, что предложение неправильное, и не принять его. В чём смысл? Должны ли разработчики беспокоиться о вопросах оптимизации?

Уже давно было объяснено, что inline больше не имеет отношения к оптимизации. Этот спецификатор влияет лишь на то, как определение функции взаимодействует с One Definition Rule, и не более ни на что. В С++17 появятся inline-переменные, где новая роль inline сияет во всей красе.

Это вранье. Все статические объекты в С инициализируются нулями по умолчанию.

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

Различия С и С++ — огромны и фундаментальны. С — lvalue-discarding language, C++ — lvalue-preserving language. Уже этого достаточно для того, чтобы заявлять, что любые сходства между этими языками — не глубже уровня сходного синтаксиса.

Теперь — да.

Но вообще, для С ниша на сегодня понятна. А С++ — действительно стал монструозен… Но опять же, это сугубо лично моё мнение, и я его ни в коем разе не навязываю.
Не только ваше мнение, я тоже считаю, что С++ превратился в страшного мутанта.
В своей работе я использую лишь подмножество С++, наиболее понятное и очевидное. Этим я занимаюсь уже много лет, но ни разу язык не поднялся называть себя программистом С++.
Нет, неправда. Именно стандарт языка С гарантирует инициализуцию нулями всех статических объектов (неинициализированных явно пользователем).

> 6.7.8 Initialization
> 10 [...] If an object that has static storage duration is not initialized explicitly, then:
> — if it has pointer type, it is initialized to a null pointer;
> — if it has arithmetic type, it is initialized to (positive or unsigned) zero;
> — if it is an aggregate, every member is initialized (recursively) according to these rules;
> — if it is a union, the first named member is initialized (recursively) according to these rules.
Ага, конечно, видимо именно потому что в C++ нет обратной совместимости с C, вы можете использовать в нем одновременно: массивы C ([]) и массивы C++ (std::vector), строки C (char*) и строки C++ (std::string), вывод C (printf) и вывод C++ (std::iostream), выделение памяти C (malloc/free) и выделение памяти C++ (new/delete), указатели C (*) и ссылки C++ (&), и т.д, и т.п.
Пара ремарок.
1) Массивы C++ — std::array.
2) Желаю удачи с неявными кастами из\в void*.
О, ну еще лучше — значит вместо двух типов массивов их теперь в C++ целых три. И на Stackoverflow наверняка есть куча вопросов про то, чем std::vector отличается от std::array, а std::array от T[]. Конечно, не только в C++ можно делать одно и то же разными способами, но дизайн языка от этого лучше не становится.
Невежество не повод для гордости. std::vector — не массив, а очередь с произвольным доступом. Так что типа ровно два, и один из них унаследован от C.
Требование о выделении памяти под данные цельным куском — вполне себе признак массива.
Проще различать их как vector — данные в куче, array — данные на стеке. Соответственно размер array изменить нельзя.
Содержимое vector может перемещаться в пространство-времени, то есть любое изменение размеров vector'а может привести указатели на произвольные элементы вектора в негодное состояние. Согласитесь, это не стандартное поведение массивов по эту сторону планеты.
любое изменение размеров vector'а может привести указатели на произвольные элементы вектора в негодное состояние

Вовсе не любое, а только такое, после которого «new size is greater than the old capacity».
И как, согласно этому описанию, vector перестаёт быть массивом?
realloc() тоже делает все указатели на элементы в памяти невалидными, но он таки выделяет память под массив, динамический, в куче… это я точно не про vector сейчас?
Давайте быть корректными до упора, malloc, realloc и free работают с блоками памяти, они совершенно не интересуются, массив это или нет. Не забывайте, *alloc принимают не число элементов, а размер в байтах. realloc завершается успешно, даже если из ста элементов удалось переместить 3,141592. π скопированных элементов — это нормальное поведение массивов?
А почему забыли calloc?
они совершенно не интересуются, массив это или нет.

Естественно, ибо ни железяка, ни рантайм, ни что-либо ещё не знает о существовании каких-то массивов о которых говорит эксперт с хабра.

Типы — это свойство интерфейса. На этом уровне — указателя.

блоками памяти

Школьное название, но ладно. Удивлю, но память и есть массив адресуемых элементов. Опять же на уровне языка этого нет.

Не забывайте, *alloc принимают не число элементов, а размер в байтах

А что такое байт? Это не элемент?

realloc завершается успешно, даже если из ста элементов удалось переместить 3,141592. π скопированных элементов — это нормальное поведение массивов?

Чё? Если вектор на аппенде зафейлится, то чем его поведение будет отличатся от реалока?

UFO just landed and posted this here
Очередное игнорирование всего и вся.

На адекватном уровне типизации — нет.

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

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

Опять какая-то брехня. Какой ещё объект? В памяти нет никаких объектов. Память это и есть массив адресуемых елементов.

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

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

Всё просто.

И без разницы как это дальше интерпретировать — память это массив. По определению.

UFO just landed and posted this here
На уровне памяти и массивов не существует. На уровне памяти вся память — один большой единственный массив.

Ой балаболка. Дак память массив или не массив? Ну ладно тут лужа.

А теперь подумаем, о чём же мы говорили? Ой мы говорили о:

блоками памяти


Т.е. кусок массива( блок есть кусок) не является массивом? Вот это новость.

Объект — это, если сильно упрощать, вот эта самая адресуемая штука. int a; struct {} foo;, и так далее.

Не верно. Объекты существует на уровне языка — это интерпретация памяти. На уровне памяти же никаких объектов не существует.

Собственно на этой логике построены юнионы. Ну куда там балаболам.

Вы не можете так относиться в памяти к C++.

Опять какие-то пустые утверждения. На основании чего вдруг я не могу? Поподробнее.

А объекты вы через memcpy копируете? Даже с виртуальными функциями и всем таким? Норм вам тама.

Какие такие объекты? Причём тут объекты. Говорилось про «блок памяти» — блок памяти есть массив. С этим вы выше согласились. Зачем эти ваши потуги? Какое они имеют отношения к теме?

Да, объекты копируются мемкопи — любые. И объясняется этот факт очень просто. Вы там выше балаболили про new, дак вот как работает new? Правильно через sizeof.

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

Тут вы пытаетесь слиться на тот факт, что виртуальные(как и любые) куллстори это могут быть не только данные, но и какая-то левая логика. Но потуги не имеют смысла, ибо левая логика не есть данные и не есть память.

При это какое отношения имеет ваш высер к той цитате на которую вы отвечаете — вы не ответите, ибо он отношения не имеет.

Заметим. Высер аналогичный той тактике, что я описал в каком-то комменте. Мы высираем какую-то не относящуюся к делу херню и на основании «потому что я так сказал» делаем вывод, что «оппонент дурак».

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

Балаболка пытается меня ловить на том, что я якобы куда-то сливают. Можно мне доказательства?
UFO just landed and posted this here
На уровне процессора и ассемблера — массив байт. На уровне языка — нет.

На уровне языка так же. В целом споры с балаболами лсными бесмысленны — зачем я этим страдаю?

На уровне языка память никакой типизацией не обладает. Собственно поэтому аллокаторы и возвращают void *.

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

Да, и эту логику юнионы инкапсулируют (и, кстати, поговаривают, писать в один член юниона, а читать из другого — UB). Но инкапсуляция — для балаболов, чоткие пацаны смешивают понятия, ясно.

О боже, опять какой-то убогий высер.

Чтение и записать в любые члены юниона не является уб. Ты получишь ровно то, что там есть. Это валидная операция.

Балаболка балаболит про УБ уровня представлений данных. Это уб следствие того, что представление типов данных в языке не определено. К памяти отношения не имеет. К возможности её чтения то же.

Потому что копировать объекты через memcpy вы не можете, например.

Какие такие объекты? Мемкопи копирует память. Копировать представление в памяти любого объекта я могу.

В целом потуги ясно. Балаболка обосралась и пытается съехать с темы памяти и объектов в памяти на тему объектов в логики смеси данных и исполняемой логики.

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

Вон из профессии.

Убогая ламрюга. Как это прекрасно, когда обосравшийся балабол начинает съезжать на левые понятия, а потом что-то из себя строит.

Мешает семантика языка и наличие конструкторов копирования, которые надо вызывать. Копировать вы можете только POD-типы (в C++03, в C++11 чуть сложнее).

В целом слив пошел по тому пути, что я заранее определил.

Какое отношение семантика языка имеет к памяти?

Этот тред тому доказательство, юное создание.

Действительно. Что-то на основной мой пост ты не ответил. А теперь как и любая балабокла пытаешься юлить, в чём-то меня обвинять и прятаться за таких же лсных балаболов как ты.

Ничего удивительного в этом нет. Из таких убогих состоит людей помойка.
UFO just landed and posted this here
> Естественно, ибо ни железяка, ни рантайм, ни что-либо ещё не знает о существовании каких-то массивов о которых говорит эксперт с хабра.
Напомню, что у функций Си в параметрах элементарные типы, либо структуры, либо указатели на них. Вызвать printf с первым параметром типа FILE получится после изнасилования компилятора. Да, си, а вслед за ним и С++ позволяет насиловать как компилятор, так и железо непосредственно, но нисколько не поощряет такое поведение.

> Удивлю, но память и есть массив адресуемых элементов.
На уровне железа? На уровне железа, раз уж вас так сильно тянет вниз, у нас есть блоки SDRAM или других типов, которые не обязательно имеют один размер, не обязательно имеют сплошную или одномерную адресацию и не обязательно являются непрерывными. На уровне ОС? Блоки (да что-же за школьное слово-то!) виртуальных адресов, проецируемых на те самые физические адреса. Уже на уровне ОС память не является одномерным массивом, так как несколько приложений способны иметь одинаковую локальную виртуальную адресацию, которую ОС распихивает и разгребает.

> Опять же на уровне языка этого нет.
Ну давай, завкаф филфака, удиви, что же есть на уровне языка?

> А что такое байт? Это не элемент?
Нет, если у меня массив int.

> Чё? Если вектор на аппенде зафейлится, то чем его поведение будет отличатся от реалока?
Выбрасыванием исключения std::bad_alloc? Не знаю… Чем же такое поведение отличается от ошибки выделения памяти в том же Питоне?
Напомню, что у функций Си в параметрах элементарные типы, либо структуры, либо указатели на них.

Вот это новость. Меня тутошние эксперты учат Си. Как это мило. В функцию передаются аргументы через копирование. И отсутствие передачи массивов, функций и прочего — это свойство не функций, а некопируемости этих объектов. Так работает присваивание в си, что присваивание некопируемоего объекта равняется присваиванию указателя на оный.

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

Вызвать printf с первым параметром типа FILE получится после изнасилования компилятора.

Чего? Поподробней про насилие при передачи указателя.

На уровне железа?

На уровне того, что там указано. А раз иного не указано, то уровень того о чём собственно говориться — т.е. си, да и в целом программном уровне. Ибо любая программа работает на этом уровне и ничего снизу к ней отношения не имеет.

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

На уровне ОС? Блоки (да что-же за школьное слово-то!) виртуальных адресов, проецируемых на те самые физические адреса. Уже на уровне ОС память не является одномерным массивом, так как несколько приложений способны иметь одинаковую локальную виртуальную адресацию, которую ОС распихивает и разгребает.

Из этого ничего не следует. Зачем мне об этом рассказывать? От этого этого определение памяти не меняется.

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

Это верно и для уровня ОС и для уровня приложения. «блоки» на уровне ОС есть ни что иное как объект уровня менеджмента, а не памяти. В любом случае всё это в конечном итоге эмулирует то определение памяти, что я дал.

Точно так же и процессор эмулирует для ОС определение памяти, что я дал. А далее это уже уровень не программный.

Ну давай, завкаф филфака, удиви, что же есть на уровне языка?

Зачем мне задан этот вопрос? Из чего он следует?

Может не ясно почему логика рантайма и логика программиста не являются уровнем языка?

Нет, если у меня массив int.

Опять 25. Что за тотальный аутизм. Массив, а в данном случае указатель — есть интерфейс, а не память. Нет никаких различий между int и не int на уровне памяти. По определению и языка, и матчасти и логики.

Выбрасыванием исключения std::bad_alloc?

Опять какая-то ахинея вместо ответа. Вы написали херню:

realloc завершается успешно, даже если из ста элементов удалось переместить 3,141592. π скопированных элементов — это нормальное поведение массивов?

Мало того, что это какая-то херня, да и к тому же вы написали «это нормальное поведение для массивов?» — т.е. намекая на ненормальное поведение.

Вас спросили чем это поведение отличается от «массива» вашего. Вы ответили «не знаю». О какой вообще вашей вменяемости может идти речь? Если вы не знаете — нахрен вы это пишите?

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

Да ну?


int a[10], b[10];
a = b; // error: assignment to expression with array type

Капитан Очевидность сообщает: некопируемый объект — он реально некопируемый.

> Так работает присваивание в си
Вы не поняли. Я знаю, что везде передаются указатели. Но на уровне языка передаются указатели на тип. Не абстрактный адрес, а вполне конкретные свойства объекта. Если типы структур или сигнатуры методов не совпадают, компилятор выдаёт ошибку. Компилятор. Вы можете подавить его, заставить быть тупой железякой. Но из коробки он весьма умный и въедливый парень.

> Чего? Поподробней про насилие при передачи указателя.
http://coliru.stacked-crooked.com/a/f200471b2d6ca492

> Зачем мне задан этот вопрос?
>> массив адресуемых элементов. Опять же на уровне языка этого нет.
Я просто поинтересовался, как же так, на уровне языка нет массивов, если есть operator[]?

> По определению и языка
http://coliru.stacked-crooked.com/a/45b48688dc07146a
Не сходятся концы.

> ахинея
Мне очень жаль, что машинный текст не способен передавать интонации голоса, как способен это делать рукописный. Последние два предложения следовало читать с саркастически-издевательской интонацией.
Я действительно не знаю, как питон даст знать об окончании памяти, но я точно знаю, что после неуспеха выделения памяти вектор отменит эту операцию, не потеряв ни одного из уже имеющихся элементов. И тем более, не будет мне петь «Всё хорошо, прекрасная маркиза...», скопировав мне три с половиной землекопа. Для меня очевидно, что на уровне языка корректно только такое поведение.
realloc же его нарушает, что даже с точки зрения языка Си не очень корректно, и именно это заставляет си-программистов каждый раз бить его по голове операторами явного приведения адреса памяти к указателю на тип. Хорошо, что у плюсовиков такой проблемы нет…

Структуры, аналогичные std::vector по свойствам, часто называют динамическими массивами.

Тогда претензия не ясна совсем, ибо та же Java поставляет Vector, а c# — List, с абсолютно идентичной функциональностью. И каждый из них всё ещё позволяет выделять куски памяти для наивного массива, который с квадратными скобками.

Ну вот в статье и собрали аналогичного качества претензии сразу ко всем языкам :)

Вопрос же не в том, массив/не массив или скомпилируется/не скомпилируется C файл. А в том, что из-за решения поддержать совместимость с C в языке существует большое количество дублирующих друг-друга сущностей. Автор считает это недостатком и он в этом не одинок. Вот здесь, например, более подробный разбор — http://yosefk.com/c++fqa/
Ну покажите мне тогда популярный ЯП без шизофрении.
Опять же не верно. С++ не поддерживает совместимость с си — он и есть си. Напишу и тут. Он создавался как надстройка над си. Он существует как надстройка над си. Вся логика уровня языка в нём сишная.

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

При этом ничего не мешает эмулировать логику си своей логикой. Вот допустим, как я уже выше писал, в си на уровне языка не существует функций. Просто кусок данных, который компилятор скомпилировал и создал объект — дал ему имя. Линкер его прилинковал. На уровне кода это тупо указатель/ссылка.

С++ экпортировал эту логику. Добавил к ней ту же перегрузку, но опять же в С++ функции на уровне языка не появились — опять же только указатели. Опять же те же самые отдельные куски данных. Что мешало в С++ вывести функции на уровень языка? Они итак уже стали несовместимы с сишными на уровне бинаря. Правильно — ничего. Можно было бы на этом реализовать сишное поведение и прочее? можно. Почему это не было сделано? Правильно, ибо С++ это си.

И всё просто в С++ перегруженная функция была бы одной функцией, а не множеством. Её можно было бы спокойно передать как некую общую сущность. Это собственно крестовики и кастылили создавая объект и реализуя перегрузку через перегрузку оператора (). Ибо они понимали, что этот функтор — это и есть функция уровня языка, а не убогий сишный кастыль из 60-х.

И так со всем.
UFO just landed and posted this here
Эм, что? Вы макросы с шаблонами точно не путаете?

То. Хотя о чём это я. Экперты тутошние даже не знают что такое шаблоны.

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

Это что? Хотя о чём это я. Это ведь не ответы — это просто невежество.

Ладно — буду срывать покровы. Шаблоны работают точно так как препроцессор — занимаются тупой подстановкой значений. Только подставляют они сущности уровня кода( о чём я писал выше) на уровне кода есть значения и типы. Ну и целом они более мощны, ибо созданы были не в 60-х( в том же препроцесоре запрещена рекурсия) поэтому и тормозят так безбожно.

Т.е. это такой же отдельный от языка уровень. Но который уже более стильный и работает не с текстом. В остальном проблемы всё те же и использование то же.

А значит ли это, что си — это ассемблер?

Эти убогие попытки. Нечего сказать — скажи херню.

А какую логику из ассемблера экспортирует си на уровень языка? Поподробнее.
UFO just landed and posted this here
Мне вот интересны. Вы такой балаболящий эксперт, но почему же вы не ответили внятно на это: https://habrahabr.ru/post/315152/#comment_9916208. Тем все подробно разобрано. Правильно, ибо обосрамс.

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

Как минимум, есть частичные специализации

И что же из этого следует? Правильно — ничего. Это не тупая подстановка значений?

а значит, есть паттерн-матчинг

Нету. На уровне шаблонов есть только генерация тонны типов и в этих тоннах говна компилятор уже копается — опять же тупым перебором с приоритетами.

Да и опять же — к чему эту потуги? Это что-ли что-то меняет? Либо делает мои слова неверными?

условные операторы

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

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

и полная Тьюринг-полнота.

Как и в брайнфаке.
На шаблонах это всё немножечко сложнее.

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

Сделайте мне

Опять пошел какой-то байт на трату моего времени и заведомо ущербанские предъявы.

Как им образом из:
В остальном проблемы всё те же и использование то же.

Следует «я бахну на макросах то же самое, что и на шаблонах». Правильно — никаким. Просто обосрамс и начало пасты ахинее.

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

UFO just landed and posted this here
>очередь
это что-то новенькое!
Массивы C++ — std::array.

Это не уровень языка. Это не более чем поле с сишным массивом.

Желаю удачи с неявными кастами из\в void*.

В крестах есть какие-то проблемы с неявным кастом в воид? Вот это новости.

Это косметическое отличие. Если уж говорить об изменении кастов, то говорить надо об уменьшении силы сишного каста в крестах, а вернее наделение его логикой крестового каста. Но опять же это косметика, ибо ничего на уровне языка не поменялось.
На уровне языка в С++ нету никаких массивов, строк( строк так же нету и в си, кроме левой логики с инициализацией литералов, но это такое), вывода( причём тут вообще вывод?), опять же путанье ключевых слов и операторов. Операторы new/delete являются по сути лишь алиасами( я знаю про новомодные куллстори) к маллоку и никакой новой логики не не несут. Ссылка не является альтернативой указателя. Это дополнительная сущность.

С++ «обратно совместимый» не потому, что он эмулирует поведение си — он и есть си. Изначально существовал как надстройка над си, да и сейчас существует. Никаких фундаментальных даже расширений сишной логики уровня языка нету, я уж не говорю о своей.

Именно из-за того, что С++ есть си в нём и есть та тонна проблем о которой я писал ниже.
UFO just landed and posted this here
А что произойдёт, если вы аллоцируете массив из N объектов, и какой-то из конструкторов этих объектов бросит исключение?

Конструкторы не имеют никакого отношения к аллокации. Опять же отвечающий мне путает operator new и new, но такое бывает.

Из этого следует, что любую программу на C++ можно собрать компилятором C, а это, очевидно, не так.

Не следует. На основании чего это следует?

Из этого следует лишь то, что всё то, что есть в С++ и си — это одно и то же — это си.

Но опять же всё это не важно, ибо вам ответ не более чем попытка юлить. Вам было сказано это в контексте:

С++ «обратно совместимый» не потому, что он эмулирует поведение си — он и есть си.

Естественно из этого понимается то, что говорится только о частях эквивалентных( в вашем понимании совместимых) с си.

UFO just landed and posted this here
В коде new используется куда чаще, чем operator new, поэтому обсуждать последний, особенно для доказательства, что в C++ ничего принципиально нового нет, одни прокси к malloc, не имеет особого смысла.

Слив. Я уже опустил слив с массивами из С++, которых не существует. И перлами вида «ссылка из С++ есть указатель из си».

выделение памяти C (malloc/free) и выделение памяти C++ (new/delete)


Чтобы оратор опять не слился на свои интерпретацию понятия «выделение памяти» — разберём его цитатку.

Он назвал «выделением памяти» маллок. Т.е. оратор использовал понятие «выделение памяти» как выделение памяти в общепринятом значении.

А далее оратор называет аллокатором в С++ new, что является неправдой. Ибо new нихрена не аллокатор, а создатель объектов.

И тут оратор загнал себя в угол, ибо он говорил не про объекты, а про память. А теперь же он слился на объекты.

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


Очередной слив. Полный игнор уличения оратора в подлоге. Ни о какой программе и ни о каком языке речь не шла. Речь шла о:

С++ «обратно совместимый» не потому, что он эмулирует поведение си — он и есть си. Изначально существовал как надстройка над си, да и сейчас существует.

В данном случае( и это разобрано выше) говорится именно о части С++, который типа совместим с си, а при этом на самом деле и является си.

А далее если учитывать то( это я уже выше/другх постах разбирал) то, что в плане языка С++ состоит из си с прикрученными классами( исключениями и rtti, но опять же это в больше степени левый рантайм, а не уровень языка), то С++ ни что иное как си. Но это уже к делу не относится — это про следующие предложение которые вы не пастили. Хотя вы и не пастили и первое, иначе без вранья и передёргивания отвечать было бы нечего.

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

Очередные кидания левыми понятиями. Если это надмножество, то о какой такой «обратной совместимости» вы говорили выше?

А при этом если надмножество С++ является в плане языка состоящим на 95% множества Си, то является ли С++ каким-то самостоятельным множеством? Да и с любыми раскладами — является ли С++ самостоятельным множеством?

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

UFO just landed and posted this here
Окей, тогда мой ответ (не ораторский): в C++ есть не только operator new.

Из этого ничего не следует.

Совместимая с С часть совместима с С, ломающие новости.

Опять какие-то убогие попытки написать херню. Говорилось не о совместимости, а о причинах этой совместимости. Хотя опять же С++ не совместим с си.

То есть, программу на С++ можно собрать компилятором С? Иначе я не понимаю смысла этого утверждения.

Очередная херня. Дело не в том, что кто-то чего не понимает — дело в том, что кому-то сказать нечего и начинаются инсинуации.

Смысл уже давно был определён. С++ не является языком совместимым с си — он является си в той части в которой он совместим с ним. Ибо по определению понятие «совместимости» не подразумевает того, что совместимое является тем же самым, что и то с чем собственно оно и совместимо.

Об обратной совместимости пересечения, очевидно. Вы вообще понимаете, что такое «обратная совместимость»?

Опять какой-то невнятный высер. Что из этой потуги должно следовать?
Откуда тут число 95% взялось? Почему не 99%? Не 42%? Не 0.01%?

Очередная потуга ещё более убогая чем предыдущая. Был задан конкретный вопрос с конкретными условиями. Какой там число не является принципиальным — нужен чёткий ответ да или нет.

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

Вот мы видим всю убогость балаболистики. Ведь ниже сказано «Да и с любыми раскладами», т.е. заранее дан ответ на потуги про «а если не 95%». Но зачем отвечать нормально? Правильно — херня наше всё.

Вы назвали язык множеством? вы. Я приписал к нему свойство которое есть и может быть у языка. Что вам не ясно?

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

Хорошо — оставим это. Определимся с множеством. Что есть «множество языка»? Из чего оно состоит?

UFO just landed and posted this here
Из этого следует, как минимум, что конструкция с new интереснее, чем прокси к маллоку.

Очередная потуга. Хотя что с вами балаболами спорить. Выше вами же было определено, что:
выделение памяти C (malloc/free) и выделение памяти C++ (new/delete)

Т.е. (new/delete) — «есть выделение памяти C++ ». Вам сказали, что это не так. В данном случае вы сравнивали аллокаторы и явно это указали. Все потуги не имеют смысла.

Но при этом является Си. Ясно.

А С++14 не совместим с С++11 — является ли он С++? А является ли CL лиспом?

В данном случае балабол пытается как и любой балабол подменять понятия. Как бэ это объяснить попроще, чтобы домохозяйке было понятно.

Вот у нас есть айфончик. У айфанчика есть коробка. Есть айфончик в чехольчике. Можно ли на основании того, что айчинчик в чехольчике не влезает в коробку сделать вывод, что айфончик в чехольчике не является айфончиком? Ведь он с коробкой не совместим, а значит имеют другую форму и габариты. Т.е. его представлению в пространстве добавлены новые свойства.

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

Если же пойдём дальше и будем учитывать только форму( ну с логикой домохозяйки иного и не дано), но тут у нас уже возникает вопрос — что определяет форму айфончика в чехольчике? Чехольчик или айфончик? Уж явно не чехольчик, но так же явно и не сам айфончик в полной мере. Хотя он без чехольчика существует, а чихольчик без него нет — это уже определяет то, что является из них основополагающим елементом.

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

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

Ну раз число не является принципиальным, я его заменю и на вопрос «А при этом если надмножество С++ является в плане языка состоящим на 0.01% множества Си, то является ли С++ каким-то самостоятельным множеством?» со спокойной совестью дам ответ «нет».

Слив засчитан.

Для любого множества элементы его подмножеств принадлежат этому множеству. Ваше определение неконструктивно.

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

На уровне доступном вам. Вот у вас, в детском садике, есть шарики на ниточке в руке у васи. Т.е. элемент есть шарик — их 3 — это множество шариков.

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

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

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

И вам привили пример. Есть функции. Функции это объект — конструкция языка. У этой функции есть неопределяющие свойства — т.е. отсутвие/наличие какого-то из этих свойств не делают функцию другим объектом.

То же самое, допустим, и с языком. Новая фишка в С++ не делает новые С++ новым объектов как язык, ибо фишка не является определяющим для определения чего-то как «новый язык».

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

Из допустимых программ, очевидно.

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

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

Язык определяется по набору конкретных лексем и правилам работы с ними. Никаким образом язык не определяется множеством «текстов», ибо определение не имеет смысла.

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

UFO just landed and posted this here
Давайте я буду уже третьим (как минимум) человеком, который вам напишет:

Фраза, которую вы сказали: «C++ является C» чисто математически должна означать «Код на C++ должен быть успешно скомпилирован компилятором C».

То, что вы пытались донести до аудитории, повидимому, должно было звучать наоборот: «C — это часть C++». Но с этим, вроде, тут никто и не спорил.

Когда речь заходит об обратной совместимости, предлагаю вам простой эксперимент.

Напишите программу вида:
void foo() {
}

Укажите расширение файла ".c" и скомпилируйте ее в DLL (или shared object). Затем создайте другую программу вида

extern void foo();
int main() {
    foo();
}


Тоже укажите ".c". Скомпилируйте ее и слинкуйте с первой динамически.

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

А теперь, опираясь на ваше утверждение об обратной совместимости, давайте попытаемся переименовать оба файла в ".cpp" и, соответственно, воспользоваться компилятором C++, вместо C.

Если вы попробуете это сделать, вы обнаружете, что процедура линковки не пройдет успешно, так как компилятор C++ не найдет в вашей библиотеке функцию «foo()». Если вы запустите nm, вы заметите, что функция называется иначе.

Это называется name mangling.

Для того, чтобы включить линковочную совместимость с Си, существует, какмы все знаем, директива extern "C". Которая, в свою очередь, непонятна компилятору C — если вы напишете ее в файле ".c", он его не скомпилирует.

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

И мы вынуждены иcпользовать макроопределения типа __cplusplus. Но вы же не считаете использование макросов способом достижения совместимости, так ведь? Потому что если считать, то можно сделать Си совместимым хоть с Фортраном, хоть с Ассемблером.

Таким образом теорема об отсутствии обратной совместимости между C++ и C доказана предъявлением контрпримера.

Удовлетворены?
То, что вы пытались донести до аудитории, повидимому, должно было звучать наоборот: «C — это часть C++». Но с этим, вроде, тут никто и не спорил.

И это тоже неверно.


gross@unterwelt [10:29:58] [~] 
-> % clang -std=c++11 -o test test.cpp
test.cpp:4:8: error: cannot initialize a variable of type 'int *' with an rvalue of type 'void *'
  int *a = malloc(sizeof(int));
       ^   ~~~~~~~~~~~~~~~~~~~
1 error generated.
gross@unterwelt [10:29:59] [~] 
-> % mv test.c{pp,} 
gross@unterwelt [10:30:22] [~] 
-> % clang -std=c99 -o test test.c
gross@unterwelt [10:30:32] [~] 
-> % 
Ну да. Проглядел. Мой пример, собственно, тоже доказывает формальную несовместимость в обе стороны.
UFO just landed and posted this here

Я не пишу на плюсах, поэтому не знаю большинства различий, но это первое, что пришло в голову. Можно ещё какое-нибудь (a=b)=c;, которое валидно в плюсах, но не в случае си.

Из этого следует, что любую программу на C++ можно собрать компилятором C, а это, очевидно, не так

Если С++ — это «С плюс надмножество», то любую программу на С можно собрать компилятором С++
UFO just landed and posted this here
Мне вот интересно. Почему, когда вас ловят на дырявости ваших суждений — вы начинаете юлить и рассуждать на левые темы?

При этом далее пошел не только слив, но и враньё. А вернее паста выдранного из контекста куска, хотя на что вы, балаболки, ещё способны.

«я не понимаю» — это не ответ. Вы можете не понимать только потому, что в моих рассуждениях есть какие-то дыры, либо потому, что вы дурак. Если никаких дыр и фактов слабости суждений у вас — вы дурак. А это ваша проблема.

В целом ваши потуги предсказуемы. Тот, кто совсем лсный балабол обвиняет меня в том, что крестов я не знаю. Кто-то более-менее вменяемый понимает о чём я пишу, а так же то, что написать это без знания этих самых крестов нереально. Но опять же тактика перехода на личности не меняется. Потуги строятся на «оппонент дурак», игнорирования неудобных вопросов да и вообще всех вопросов. Ну и конечно же враньё, подлоги, чернуха уровня «расскажу какой он дурак все округе» ну и в конечном итоге всё сводится «а чего добился ты?», либо «все за меня/ авторитеты за меня» — т.е. перекладывание ответственности во внешний мир.

Что мы собственно и видим. Ничего не меняется — каждый балабол уверен в том, что можно нести любую херню и он прав по факту.
UFO just landed and posted this here
Логика проста и убирается в одной емкой фразе, которую нам, повидимому, пытаются донести, явно не произнося: «C, C++ — всё одно говно… Ну, не совсем одно, но на 95% — точно».

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

Я, кстати, выше доказал, что это тоже не так. Линковка подведет из-за name mangling-а.

Не подведет, если собирать программу целиком, а не отдельные модули

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

Вот это, мне кажется, уже буквоедство. Компиляция без линковки — бессмысленный процесс. Так что совместимость, если она есть, должна распространяться на все фазы сборки.

Почему? Можно скомпилировать код разными компиляторами с разных языков (или разными версиями одного и того же компилятора) и скомпоновать в один исполняемый модуль. А некоторые лицензии позволят не распространять ваше ПО, не раскрывая его кодов, но поставляя объектники, которые можно будет скомпоновать с другими обновившимися частями. Не вижу никакого буквоедства.

1. Что из перечисленного вами предполагает, что линковки вовсе не будет?
2. Какое перечисленные примеры имеют отношение к совместимости между C и C++, обсуждаемой в контексте данной дискуссии?
  1. Я где-то утверждал подобное?
  2. Не знаю, это же вы плавно перешли от языков и их компиляторов к фазе линковки, которая к компиляции (и, следовательно, к тому, на каком языке вообще изначально программа была) никакого отношения не имеет.
>На уровне языка в С++ нету никаких массивов
Статические массивы есть. С сохранением типа при передаче по ссылке.

>он и есть си
Что за бред? Вы вообще писали на плюсах что-то, кроме пары лабораторных работ?
Статические массивы есть. С сохранением типа при передаче по ссылке.

Нету. И быть не может.

Что за бред? Вы вообще писали на плюсах что-то, кроме пары лабораторных работ?

Опять же тактика отвечающих не меняется. Выдираем из контекста, врём и обвиняем. Зачем уровень своих познаний( а вернее 3-х лабораторных работ) экстраполировать на меня?

Ответ на это враньё есть выше.

Я не выдираю из контекста, моя фраза про лабораторные была сделана на основе всего вашего комментария.
Опять враньё. Собственно слив засчитан.

Ну что за убогое убожество населяет эту борду. Балабола уличили в том, что он выдрал из контекста фразу про «он и есть си». А уже после этого балабол рассуждает а каких-то лабораторных и делает вид, что «выдирание из контекста» было про какие лабы.

Невероятно.
>эту борду
всё с тобой понятно
Сэр, может вы адрсом ошиблись? Какая вам тут борда? Тут сообщество разработчиков.
Это лишь поверхностное сходство сходного синтаксиса.

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

А уж то, что большинство упоминаемых вами свойств (`std::vector`, `std::string`, `C-string`, `printf`, `std::iostream`, `malloc`) вообще реализованны *на уровне библиотеки*, делают их вообще неуместными в рамках данного вопроса. Никто вам не запрещает реализовать С-style строки или `malloc` в Паскале. Это, однако, не будет свидетельством какой-то «обратной совместимости» Паскаля и С.
Не очень понимаю, какое значение имеет отсутствие «полной обратной совместимости» в контексте обсуждения недостатков языка. Мы просто про разные вещи говорим. Очевидно же, что создатели С++ ставили целью сохранить максимальную совместимость с Си (что автор статьи и считает недостатком). И то, что они в этом не очень преуспели, очков языку добавить не может.
UFO just landed and posted this here
Косноязычие не позволяет понять, что именно имеется в виду.

Я так понял, что автора напрягает отсутствие неявного преобразования.

Нет.

Да. С++ не более чем надстройка над си. Ничего своего там на уровне языка( а не сахара) нет. Вся логика работы с функциями экспортирована из си и по этой причине перегрузка функций выглядит как кастыль и работает как кастыль. Попробуйте сделать какой-нибудь std::invoke на перегруженную функцию — не получится, а проблема одна — си. Ибо на уровне языка не существует никакой перегрузки — это убогий кастыль с именами. На уровне языка даже функций нет. Только указатели, хотя тип-функция и есть, но это тупой ссылка.

И так везде. Всё что должно работать и не работает — это наследие си. Нету constexpr памяти? Си. С++ ничего не знает об объектах и памяти — этого не существует на уровне языка( да то же rtti накостылено на именах, отсюда и рефлекшена нет, хотя с чего ему не быть в статическом языке? А правильно — он нихрена не статический.). Строковые литера ущербны? Си. Опять же в си это просто глобалы с законстыленной логикой инициализации.

Различия С и С++ — огромны и фундаментальны.

Их нет. Это не отличия — это просто обвес. Нельзя сравнивать С++ с тем, аналогов чего нет в си. Если сравнивать, то имеет сравнивать именно основу и изменение в основе, которая и есть язык, а сахар и левая логика — это не язык.

Если мы сравниваем Си(чай) и С++(чай с сахаром и ложкой классиков), то мы не можем сравнивать сахар в них, либо классики, ибо их нет в первом случае. Мы сравниваем только чай. Ибо и в первом и во втором напитке основой является чай, а не сахар. И именно этот чай из С++ есть ни что иное как чай си. Ни какой-то другой чай, а именно он. И опять же от добавления в него чего-то ничего не поменяется, ибо основа есть основа.

С — lvalue-discarding language, C++ — lvalue-preserving language. Уже этого достаточно для того, чтобы заявлять, что любые сходства между этими языками — не глубже уровня сходного синтаксиса.

Это пустые рассуждения, когда сравнивается левая логика. На уровне железяки есть только копирование. И ничего иного. С++( а вернее раишные куллстори) изначально построен на подмене понятий — копирование( присваивание) объектов не есть копирование их данных, а есть отдельная вызываемая логика. Именно из этого идут все различия. На уровне же языка ничего не меняется — логика остаётся сишной( логика по умолчанию).

Т.е. в крестах просто добавили возможность менять эту логику( оставив сишное поведение — поведением по умолчанию). Из этого ничего не следует — это не уровень языка. Далее вернули сишную логику копирования и назвали её «перемещением», что на самом деле и есть копирование.

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

Уже давно было объяснено, что inline больше не имеет отношения к оптимизации.

Кем и почему?
Этот спецификатор влияет лишь на то, как определение функции взаимодействует с One Definition Rule

Бессмысленной правило вызванное наследием Си и 60-х годов. Но мы его не обсуждаем.

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

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

Но опять же это лишь дополнительная логика инлайна для глобалов и само «встраивание» никуда не делось.

, и не более ни на что.

А не для глобалов?

В С++17 появятся inline-переменные, где новая роль inline сияет во всей красе.

Ну на самом деле это логика «определи, либо игнорируй если определено» и то, что её повесили на инлайн — из этого ничего не следует. Да и аллогично это.

После подобного опуса можно лишь добавить, что туева туча популярных языков (от Python до JS, промежая шарпами) так или иначе способна транслироваться в плюсовый код. С этой точки зрения все транслируемые языки — не более, чем надстройка.
Что из этого следует и к чему вообще это написано?

С этой точки зрения все транслируемые языки — не более, чем надстройка.

Надстройка над чем? Причём тут транслируемые языки?

Есть что ответить — отвечайте. Нечего — не отвечайте. Всё просто.
Зайдём с формальной точки зрения. Надстройка — это то, что может быть выражено через базовый функционал. С какой стороны не зайди, хоть бытовой, хоть судостроительной, хоть марксистско-идеалистической, надстройка является следствием базиса, выражается через базис и выполняет функцию оптимизации и повышения удобства работы этого самого базиса. Вы можете выразить плюсовые шаблоны через макросы? Нет? А на плюсах писать, не трогая <cstd*>? Да? Ну, значит, не надстройка, а самостоятельная сущность. А то же самое Qt или boost — надстройки, так как они целиком реализуются из чистого с++.
Если же мы расширяем термин «надстройка» до уровня «может иметь одинаковое представление на нижнем уровне», то под надстройку Си попадает множество языков, к Си, в общем, отношения не имеющих. В том числе ВСЕ языки, которые могут быть интерпретированы в Си или которые выполняются в виртуальной среде, написанной на Си. В том числе и Java, и Python, и все ЯП, прогоняемые через LLVM. А это очень много.

Далее, вы смешиваете язык, его реализацию, и отображение на машинные коды, то есть скомпилированное приложение. Я лично не встречал указания по именованию скомпилированных методов в стандарте. Так что то, что получится в итоге и какая дополнительная информация будет приложена к классу — зависит только от компилятора. Более того, вы периодически выкрикиваете «в памяти нет того-то, в памяти нет сего-то». Действительно, нет. Так что ваш трёп вообще не имеет смысла, в памяти кроме локальных ловушек для электронов вообще ничего нет, ни байт, ни бит. А вот в структуре и синтаксисе языков программирования они есть. Есть там и типы, и методы, и enum'ы. Мне абсолютно насрать, как будут они отображены на машинный язык, которых есть многие сотни, мне важно, что вот тут, сверху, у меня есть класс с тремя виртуальными методами. И вот тут, сверху, все ваши memset'ы посасывают, не будучи способными корректно скопировать виртуальные указатели.
Вот тут, сверху, с++ и с не имеют ничего общего, кроме базового форматирования. А что творится двумя этажами ниже, меня интересует при оптимизации кода, то есть «не сегодня» ©.

Что касается перегрузок, если бы вы были правы, то invoke бы сработал. Это же очевидно, он подставляет типы в шаблон, проходится поиском по имеющимся методам и выбирает из них первый подходящий. К сожалению или к счастью, он так не работает. Шаблоны — не макросы, они о другом. Кстати говоря, почему срабатывают перегрузки operator()?
http://coliru.stacked-crooked.com/a/b6b5f4ef32528ace
Конечно, порой не хватает более мощного инструмента для мета-программирования, но тут уж что есть. Я бы его, в любом случае, не стал сравнивать с макрогенератором.

Зайдём с формальной точки зрения. Надстройка — это то, что может быть выражено через базовый функционал. С какой стороны не зайди, хоть бытовой, хоть судостроительной, хоть марксистско-идеалистической, надстройка является следствием базиса, выражается через базис и выполняет функцию оптимизации и повышения удобства работы этого самого базиса. Вы можете выразить плюсовые шаблоны через макросы? Нет? А на плюсах писать, не трогая <cstd*>? Да? Ну, значит, не надстройка, а самостоятельная сущность. А то же самое Qt или boost — надстройки, так как они целиком реализуются из чистого с++.


Мне уже лень разбирать ваши потуги уровня первого класса. Это настолько фееричные высеры. Какая оптимизация? какой ещё нахрен базис. Настройка это то, что имеет основу и не может существовать как самостоятельный объект.

Является ли анальный зонд подключаемый к айфону надстройкой? По логике( вернее её отсутствию) тутошних экспертов нет. Но это ладно.

А на плюсах писать, не трогая <cstd*>? Да?

Нельзя. cstd не является языком ни в коей мере — это кусок лишь сишного рантайма. Да и не существует никаких реализаций крестового рантайма не основанного на сишном.

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

А далее мы задаём правильный вопрос — если из С++ выпилить си, то что останется от С++? Правильно — ничего. Даже синтаксиса не останется, но опять же к синтаксису я не придираюсь.

Если же мы расширяем термин «надстройка» до уровня «может иметь одинаковое представление на нижнем уровне»

Опять какой-то убогий высер. С++ является си не на уровне какого-то там конечного представления — он является им на уровне начального преставления.

Для ламерков и балаболов это слишком сложно. Банальный пример с теми же функциями — std::decay -это что? Правильно типичный пример экспортированной из си логики.

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

Именование тут не причём — очередной убогий высер. Дело в том, что по определению перегруженные функции не являются одной функций, а являются разными функциями — почему? Правильно — по той причине, что в си нету перегрузки функций.

Я лично не встречал указания по именованию скомпилированных методов в стандарте.

Причём тут методы? Если говорилось о функциях? Ну а далее всё просто — перегруженные методы являются одним методом? Либо разными?

олее того, вы периодически выкрикиваете «в памяти нет того-то, в памяти нет сего-то». Действительно, нет. Так что ваш трёп вообще не имеет смысла, в памяти кроме локальных ловушек для электронов вообще ничего нет, ни байт, ни бит.

Очередной убогий высер. Про какие-то там электроны.

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

Концепция памяти на уровне языка описана.

А вот в структуре и синтаксисе языков программирования они есть. Есть там и типы, и методы, и enum'ы.

С т.з. памяти( и это описано на уровня языка) тип имеет только одно свойства — sizeof. Никаких иных свойств у типа с т.з. памяти нет и быть не может.

Тип это не про память — тип это про интерпретацию данных. Интерпретация данные к памяти отношения не имеет — это исполняемая логика.

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

Очередной убогий высер. Никто ни про какие машинные языки не говорил. Говорилось про память. Нигде на уровне языка не существует никакого типа у «блока памяти» чем-то распределённого, а в том контексте аллокатором динамическим. Это определено на уровне языка. Существуют типы памяти, аля динамическая, статическая, локальная и прочее, но это к делу отношения не имеет. Она ничем друг от друга не отличается — это свой понятия моеделей менеджмента этой памятью на уровне языка, либо за его уровнем.

Причины сливая я уже описал. Классы как сущности совмещающие логику исполнения с данными являются любимой темой слива лсных балаболок. Инвариант валидного состояния конструкции поддерживается рантам логикой. К памяти это отношение не имеет. Уровень памяти как копировался мемкопи так и копируется.

Что касается перегрузок, если бы вы были правы, то invoke бы сработал. Это же очевидно, он подставляет типы в шаблон, проходится поиском по имеющимся методам и выбирает из них первый подходящий.

Что? Какая-то неведомая херня.

К сожалению или к счастью, он так не работает.

О боже, днище не понимает почему не работает инвок. А я поясню. Он не работает по той причине, что невозможно в функцию передать функцию. Т.е. функции на уровне С++, а вернее на уровне си представляют из себя уникальные объекты доступные по ссылке(имени)/указателю. На уровне си никакой перегрузки функций нет, а значит все работает нормально.

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

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

Кстати говоря, почему срабатывают перегрузки operator()?

Пацан реально не понимает, либо ослит? Я уже писал про оператор().

Функтор есть ни что иное как правильное представлении перегруженной функции на уровне языка. Но является один объектом вместе независимо от кол-во перегрузок у оператора. И естественно тут эксперт передаёт этот объект.

Но функтор есть ни что как кастыль. Как и все С++.

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

Шаблоны никакущий инструмент для метапрограммирования — его там нет.

Вот так и живём, что #define invoke(f, args...) f(args) может больше, чем мощные шаблоны.

В целом я не понимаю вас. Вы либо меня тралите, либо не понимаете того что такое шаблоны и почему они мощнее макросов. Одновременно с тем почему они и менее мощные.

Ещё раз — шаблоны это такой же макрогенератор, только вместо аргументов-«строк» там значения и типы. Всё. Вся шаблонная магия не имеет никакого отношения к шаблонам — эта магия мощи сишного синтаксиса и системы типов.

Если будет не лень мне — я сделаю отдельный разбор. Вдруг вы рально не понимаете.
[offtop] Я бы на вашем месте был поаккуратнее с жопными темами. А ещё читал бы своих собеседников, мало ли, вдруг они пишут что-то путное. [/offtop]

Я думал с вами ещё посраться, сказать, что Си без std* существовать не может, а c++ — запросто; что почти во всех языках перегруженные методы\функции являются разными синтаксическими единицами с разными внутренними именами, о чём можно узнать, декомпилировав те же классы шарпов и жавы; что перепрыгивание между функциями и указателями в обсирании шаблонов не имеет смысла, так как шаблоны не работают с адресами вообще, а все проблемы кастов сводятся именно к алгоритму подстановки и перебора типов, но потом…

> Нигде на уровне языка не существует никакого типа у «блока памяти» чем-то распределённого, а в том контексте аллокатором динамическим. Это определено на уровне языка.

… потом я понял, что это бесполезно. Я не могу сраться с тем, что само себя не понимает. Хотя было достаточно интересно прочитать такое полотно от человека, которому «делать больше нечего, кроме как кому-то что-то доказывать».
Можешь засчитывать это за слив, только запятые в процессе не теряй — и так речь сумбурная, хрен поймёшь.
UFO just landed and posted this here
А вообще, вы, конечно, титан. Такую флеймогонную простыню перевести. :)

Что тут сложного — кидаешь в промпт, копипастишь оттуда — вот и перевод.

Не знаю на счет "титан", но вот "перевести" — это явно преувеличение.

>>Строковая библиотека Lua по умолчанию обеспечивает только подмножество регулярных выражений, которое само несовместимо с обычными регулярными выражениями PCRE.

Почему претензия только к отсутствию PCRE? Я вообще хотел-бы что-бы Extended POSIX Regexp поддерживался.

Вообще статья ни о чём. Можно подумать, те кто пишут на любимом языке, не знают его проблем.
При этом несколькими абзацами выше перловые регулярки вменялись JS в недостатки.

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

Моего языка тут нет. Что мне делать?
Написать статью почему он отстоен, очевидно же!
• JavaScript унаследовал непонятный и проблемный синтаксис регулярных выражений у Perl.
Хотелось бы поподробнее, что в нем непонятного и особенно что в нем проблемного
• Регулярное выражение (a|[^d]) преобразует StackOverflowException в длинные строки.
Искренне не понял о чем это
В оригинале
(a|[^d]) regex throws StackOverflowException on long strings

Но автор перевода не очень шарит и/или не очень напрягался и теперь мы лицезреем такие жемчужины по всей статье.
После подобного закрадывается ощущение, что это полотно перевёл не профессиональный переводчик, а студент-психолог с помощью «Сократ Персональный» для курсовой по теме «психология хомячков в срачах в этих ваших интернетах». А, нет, всё-таки профессиональный переводчик. Жаль, такую конспирологическую теорию испортил.
Это опубликовал профессиональный переводчик. А о том кто переводил эту статью мы уже вряд ли узнаем :-)
Худшей антирекламы для «профессионального переводчика», чем такой перевод, — и не придумать.
Про Rust
> borrowck отвергает безопасный код.

Очевидно, что автоматически понять, является ли программа безопасной и корректной, в общем случае невозможно. Safe-подмножество Rust разрешает лишь подмножество безопасных программ. Поэтому глупо жаловаться, что borrow checker «отвергает безопасный код». Конечно, хочется, чтобы язык позволял более широкий спектр безопасных программ, но никогда не будет такого языка, который отвергает весь опасный код и принимает весь безопасный.

> В конце концов, «небезопасный» блок не говорит, что содержание блока вызовет неопределённое поведение

Естественно. Safe Rust в идеале гарантирует отсутствие неопределенного поведения, но обратное неверно. Если бы процитированное утверждение было неверно, то это была бы очень комичная ситуация — специальное ключевое слово, чтобы писать только некорректный код.

> это означает, что содержание небезопасного блока было ошибочно отклонено компилятором.

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

> borrowck, всё же, имеется, даже когда вы находитесь внутри unsafe {} блока или функции

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

> чтобы сотворить, действительно, волшебство, необходимо дать вызов, содержащий некоторые многословные имена вроде sliceable.unsafe_get(index).

В стандартной библиотеке нет unsafe_get. Если имеется в виду get_unchecked, то он используется для получения элемента массива без проверок на границы индексов и к borrow checker не имеет отношения.

> Никто не знает, какие правила определяют опасность.
> Это означает, что содержимое небезопасного блока является трудным для чтения, что оно по определению является слишком сложным, чтобы быть очевидно правильным, что оно нечётко задано и должно быть написано на коде низшего уровня.

Писать unsafe-код корректно в Rust действительно сложно. В Rustonomicon об этом хорошо написано.

Зато известно, какие правила определяют «безопасность» в терминах Rust. Эти правила компилятор проверяет и не даст вам ошибиться. Так что писать на безопасном подмножестве можно вполне спокойно.

> У Rust есть исключения. Он называет их тревожными и редко использует их, но у него они есть, и ваш небезопасный код должен быть транзакционным в отношении безопасности памяти. До сих пор они имели примерно такой же успех, последовательно соблюдая это, какой имели разработчики в C++ (за исключением тех разработчиков в C++, которые запрещают исключения, как, например, Google).

Непонятно, в чем проблема. На C++ можно писать код, безопасный по отношению к исключениям, и в Rust ничуть не меньше средств для этого.

> Таким образом, «безопасность» Rust позволяет делать существенно меньше ошибок в чрезвычайно простых кодах, но не помогает в сколько-нибудь сложных.

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

> Точки с запятой и неприятный синтаксис :: получены в наследство от С++. Также унаследован ещё более безобразный шаблонный/универсальный синтаксис.

Дело вкуса.

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

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

> Чрезмерно кратко поименованные типы и ключевые слова, которые не передают их назначение, как, например, impl и ().

Плохие примеры. «impl» — сокращение от «implement», и код вида «impl MyStruct» или «impl MyTrait for MyStruct» читаются очевидным образом. () — пустой кортеж, частный случай синтаксиса (T1, T2, ...). В чем тут проблема, непонятно. Я бы лучше поругался на ключевое слово type, которое мешает называть этим словом переменные и функции.

> mut означает исключительный, а не изменчивый (mutable).

Нет, «mut» означает «изменяемый». Например, «let mut x = 1;» — декларация изменяемой переменной (без mut была бы константная). В ссылках "&mut x" также означает «изменяемый», а исключительность уже следует из правил Rust.

> &Mutex означает изменчивый (mutable)

Mutex и RefCell являются в некотором роде исключениями. Использование этих типов говорит, что мы можем безопасно изменять один и тот же объект из нескольких мест. Имея &Mutex, вы можете получить из него &mut T и изменить объект, но сам Mutex передается по константной ссылке (&, а не &mut), создавая иллюзию, что объект неизменяем. Сделано так потому, что borrow checker просто не разрешит создать несколько неконстантных ссылок на один и тот же объект. Выглядит не очень очевидно, но не так уж и страшно.

> а &mut str — неизменяемый (immutable).

Да, тип str вообще особенный и вносит много путаницы.

> Чрезмерно кратко поименованные типы и ключевые слова, которые не передают их назначение, как, например, Vec и Cell.

Дело вкуса. При желании можно переименовать тип при импортировании.

> Большинство думает, что Rust имеет два типа строк…

Нет ничего плохого в том, чтобы разграничить разные типы строк. String — строка в utf-8. CString — нуль-терминированная строка в произвольной кодировке (прямо как в C). OsString — строка в формате, используемом в нативном API текущей ОС. С преобразованиями между этими типами проблем нет, везде есть соответствующие методы. Ну, а &str, &CStr и &OsStr — это позаимствованные строки в соответствующих форматах.

> Повсеместное неявное преобразование (типа) означает, что справочные документы практически бесполезны. Можно взять Vec, поскольку он неявным образом преобразует в &[T], например, и можно использовать для циклов с Vec и &[T], но результат будет немного различающимся в зависимости от того, что используется.

Видимо, имеется в виду Deref. Во-первых, реализованный Deref описывается в документации типа. Во-вторых, не Vec, а &Vec автоматически преобразовывается к &[T]. И результат итерирования по &Vec и &[T] будет одинаковым. А если итерироваться по Vec, то результат, конечно, будет другой (вектор будет разрушен). А вот Vec к &Vec автоматически преобразовываться не будет.

> Не совсем повсеместное преобразование (типа) означает, что ваш код оказывается замусоренным тарабарщиной вроде &*some_var (который преобразует интеллектуальный указатель в ссылку) и &some_var[..] (это — та самая магическая формула, которая преобразует Vec в &[T] или String в &str).

Неправда. Благодаря упомянутому выше Deref можно писать просто &some_var в обоих случаях.

> Дублирующие элементы, такие как, например, структуры кортежа и модулеподобные структуры

Tuple-structs позволяют делать структуры без именования полей, что вполне может быть осмысленно в некоторых случаях. Unit-like structs (структуры без полей) используются для построения API, например, чтобы выразить глобальный ресурс, захваченный мьютексом (часто используется в обертках сишных библиотек).

> Типы суммы — не enum. Хватит притворяться С.

Согласен, называть tagged union enum-ом — решение плохое.

> Поскольку он статически связывает всё (спасибо, Go, за выпуск этой модной штучки), вы получите тысячи, вероятно, устаревших копий кольца на вашем компьютере.

Можно делать динамическую линковку, если кому-то хочется.

> Действительно, он статически связывает почти всё. Он динамически связывает вашу программу с библиотекой, в результате чего ваши исполняемые файлы не являются, на самом деле, самодостаточными.

В оригинале имеется в виду динамическая линковка с libc. Делать это статически — вещь весьма специфическая.

> Нет пространства имён в поставке. Всё получает «креативные» имена, как, например, «ring» (набор криптопримитивов) или «serde» («serialization and deserialization» («сериализация и десериализация»), ничего?).

Согласен. В копилку: «select» — интерфейс к HTML-парсеру.

> Обобщённые типы очень распространены, и они по существу копируются и вставляются для каждого конкретного типа, с которым они используются (спасибо тебе, С++, что сделал это популярным). Вы знаете то, что делает компиляцию по сути тем же самым кодом часто ещё более болезненной?

Какие альтернативы предлагаете?

> rustc работает медленно…

Претензии к медленной компиляции, нехватке поддерживаемых платформ, отсутствию инкрементальной компиляции (кстати, в nightly ее уже начали внедрять) и хорошей IDE справедливы, но временны. Язык еще очень молодой.

Подскажите пожалуйста, когда может потребоваться использовать &mut str и какова семантика подобного выражения?
Ниже написал про &mut str. Потребоваться он может, когда нужно позаимствовать строку или часть строки и изменить ее. Проблема в том, что существует не так много изменяющих операций с строками в UTF-8, которые не меняют их длину.
> а &mut str — неизменяемый (immutable)
use std::ascii::AsciiExt;
let mut str_owned = "qwe".to_owned();
let str_borrowed: &mut str = &mut str_owned[..];
str_borrowed.make_ascii_uppercase();
println!("{}", str_borrowed);
//QWE
А вы посмотрите на реализацию этого метода:
fn make_ascii_uppercase(&mut self) {
  let me: &mut [u8] = unsafe { mem::transmute(self) };
  me.make_ascii_uppercase()
}

Т.е. на самом деле для этого необходимо преобразовать в &mut [u8]. Напрямую поменять что-то в &mut str действительно нельзя, просто нет методов для этого. Это из-за того, что нельзя менять количество байтов в позаимствованной строке (она вполне может быть подстрокой другой строки), а редактирование UTF-8 в общем случае может менять количество байтов практически при любой операции.

Тем не менее, &mut str — не то же самое, что &str, потому что &str в &mut [u8] преобразовать сложнее. Так что и тут mut вполне означает изменяемость.

XML и CSS уже языки программирования? О времена, о нравы!

И правильно — только Delphi безупречен ><)))
10 BASIC
20 Предлагаю не терять время и стреляться сию же минуту, без секундантов.
Ну, делфи хоть для какой-то разработки используется;)
https://github.com/search?utf8=%E2%9C%93&q=language%3APureBasic&type=Repositories&ref=advsearch&l=PureBasic&l=
UFO just landed and posted this here
Паскаля нет? Нету Паскаля? Я знал… И все мои преподаватели в техникуме знали.
Нет Паскаля. Как нет и отца его, Фортрана. Нет и Кобола. И даже нет языка Ада, а это уже богохульство.
UFO just landed and posted this here
На словах язык простой,
А на деле-то отстой!!!
Исходную статью обсуждать не буду, а вот предложенный тут перевод — ужасен более чем полностью. И если смотреть на комментарии, перевод исправляют, что бы убрать явные огрехи, но их ещё столько, что читать просто неприятно.
Ага, исправляют: «кроме GCC и шумихи» исправили на «кроме GCC и случайных троллей». (В оригинале — GCC и clang.)
В статье не хватает только одного — фото автора.
> Я не могу использовать if($a==$b) $c=$d;

И это хорошо и правильно.
На 90% выглядит как личные пристрастия автора. Не более того.

Camel-регистр никуда не годится:

XMLHttpRequest
HTMLHRElement


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

В общем, раз автор и переводчик соизволили высказать личные мнения — выскажу и я. КГ/АМ.

PS: С большой долей вероятности автор пишет на паскале/дельфи или на ассемблере. Я так думаю…
Для данных примеров есть проблема в разных способах записи аббревиатур — половина написана с заглавной, половина — целиком заглавными. Получается не слишком читабеьлно. Если писать аббревиатуры с заглавной буквы, то на мой взгляд выглядит это куда более адекватно:
XmlHttpRequest
HtmlHrElement
XML и HTML это аббревиатуры, они по любым правилам должны писаться верхним регистром же.
Чтобы понять суть — вместо каждой буквы аббревиатуры напишите нормальным камелкейсом слово, её означающее. И всё станет на свои места.
По любым правилам, на которые мы не положим болт ради удобства.
HTMLRequest — начало request'а неразличимо в отличие от:
HtmlRequest.
Еще интереснее пример выше:
XMLHTTPRequest()


И в переменных? Так?
var HTML = getHTML()


А в underscore стиле как писать? Ну на руби там.
get_HTML()


Или, может, так?
get_h_t_m_L()

С большой долей вероятности автор пишет на паскале/дельфи

Интересно, почему? Borland style guide как раз Camel рекомендует со всеми заглавными.
«Все языки пограммирования делятся на 2 категории — первые все ругают, на вторых никто не работает» — те, кого не обругали, должны насторожиться.
Некому же настораживаться, никто же не пользуется))
UFO just landed and posted this here
• Например, данная публикация была закрыта разработчиками немедленно как «WONTFIX» («Проблема есть, но решаться не будет»), несмотря на большое число пользователей, поддержавших её.

Если набраться мужества и пролистать до конца, то можно увидеть, то её таки решили.
  1. Почему мужество отстой.
Не пойму, а ассемблер-то почему проигнорирован?
Который из ассемблеров?
Критиковать ассемблер смысла нет, только платформу, для которой он написан.
За другие язык не скажу, но в Javascript единственная неудобна для меня вещь это конкатенация через "+". Да, при явном приведении типов проблем нет, но раз уж язык с динамической типизацией, могли бы такую вещь предусмотреть.
В оригинале —
'0', 0, and 0.0 are false, but '0.0' is true.

Можно посмотреть здесь — https://wiki.theory.org/YourLanguageSucks

А есть ведь ещё и 1С но видимо для него и одной статьи мало будет.
А какие у вас претензии к языку 1С? Сразу скажу, что я на нём ничего не писал.
Половина указанного про Lua, особенно про отсутствие continue описано в книге автора языка.
Про vararg — да, неудобно.
про индексацию с 1 — вкусовщина. Привык за полчаса
Добавлю свои 5 копеек:
Про глобальные и локальные переменные так же вкусовщина. В итоге область видимости переменных работает куда удобнее. Ну и вообще это видимо настолько не удобно что в ES6 добавили let (что делает, если кто не знает, то же самое что в lua работает из коробки) и попросили забыть про var.
А можете тогда объяснить почему и правда нет оператора continue?
И ведь наверняка кто-то догадается повтыкать отдельные пункты в свои тестовые задания.
80% «придирок» можно выкинуть, если учесть область применения и нязначения языков.
Любой, произвольно взятый язык программирования — отстой т.к. мир более совершенен против средств его оперирования :)

P.S. Не увидел в списке Forth (Форт) язык :)
Читал не полностью, про Rust половина — придирки, половина от незнания языка и является просто враньем. Зачем писать критическую статью, понахватав по верхам?

З.Ы. спасибо за перевод
«Closure» мало того, что в заголовке написано неправильно (clojure), так и недостатки ни о чем.
Функция Conj действует несообразно в зависимости от предусмотренного типа (присоединяет к началу векторов и заголовку списков).

Посмеялся. Наоборот как раз, функция действует сообразно типу. Делает это оптимальным способом для типа. При том, что векторы не являются последовательностями (sequences), а список (list) является. Наиболее быстрым способом вставить в список является присоединение в начало списка, в векторе в конец. И еще есть функция cons.
cons работает с последовательностями, всегда возвращает последовательность, conj работает с коллекциями, возвращает тот же тип который был передан.

Синтаксис Lisp не позволяет видеть, что представляет собой функция и т.д. — Нет визуального различия.

Еще больше посмеялся, просто потому что промпт или гугл-переводчик ничего не знают видимо о DSL или lisp?
В оригинале читается сильно легче.
Такое ощущение — словно вчерашний студент писал — когда в универе за 4-5 лет прогнал кучу курсов, много попробовал, но глубоко не вник. Вот и кричит теперь «Все гавно», «Все отстой!».

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

Или юзайте лямбда, кто мешает.

Если так подумать для реализаций одних и тех же фич разных языках почти всегда достаточно имеющегося функционала, с другой стороны, а нам это нужно?
Отличная статья! Хотя и переведено полуавтоматически, и фигня откровенная в некоторых пунктах, но в целом это можно использовать как краткий справочник по особенностям языков программирования. Мне как человеку увлекающемуся языками программирования как таковыми очень пригодится.
>это можно использовать как краткий справочник по особенностям языков программирования
Не стоит.
За все языки не скажу, но по части C/C++/Python/Haskell большая часть пунктов как минимум спорна.
Перевод чудовищный, идея статьи отличная
UFO just landed and posted this here
Добавлю:
Поскольку «nil» («ноль») может представлять любой тип, то это полностью разрушает систему типов.

nil не может собой представлять любой тип, он может быть значением указателя на любой тип
Сравнение интерфейса с нулём проверяет, является ли *типом* интерфейса ноль, а не его значение. Таким образом формируется ловушка, в которую попадался каждый Go-программист:

ЛОЛЧТО? Интерфейс — указатель на структуру, содержащую два поля — дескриптор типа и указатель на данные, проверяется соответсвие указателя на эту структуру nil'y, а не указатель на данные. RTFM
Тип ошибки Go является просто интерфейсом для функции, возвращающей строку.

И? <зануда> и не функции, а структуры с данным методом</зануда>
В Go отсутствуют исключения, а вместо этого везде используются коды ошибок, что приводит к повторяющемуся шаблону контроля ошибок

Ну, ошибки можно не только на nil проверять…
Задержанные функции могут выполнить запись в возвращаемые значения, имеющие имена функций, что может привести к неожиданностям:

ССЗБ — Сам Себе Злобный Буратино

Остально даже коментировать не буду, хотя за остальные языки тоже обидно
Насколько же холиварная статья. Но что больше напрягло, так это большое кол-во притянутых за уши пунктов. Некоторые пункты добавлены специально, чтобы опустить язык куда поглубже. Трудности перевода так же доставляют, по ходу google translate.
Перевод и правда невообразимо ужасный
• Программный интерфейс данных (Date API) считается устаревшим, но до сих пор повсеместно используется. Плана замены нет.

Интерфейс данных? Date != data
Не говоря уже о том, что замена есть (Java Time API), но это не к переводу уже.
Ощущение, что целью автора было какое-то исследование, скорее связанное с социологией или психологией, чем с языками программирования. Возможно, скоро увидим на хабре.

Авторов. Там не один автор.

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

Сожрут машинный перевод, или нет?
Будут ли обсуждать статью, которую сложно понять не прочитав оригинал?
Будут ли упоминать в обсуждении в основном кривой перевод или в основном недостатки оригинальной статьи?
Заметят ли, что сначала clang перевели как шумиху, а потом, после того, как в коментариях по этому поводу высказались — поправили перевод слова clang с шумиха на случайные тролли?


Это и многое другое в грядущей на хабре публикации об исследовании влияния статьи с машинным переводом на аудиторию. Такая публикация — единственный способ спасти репутацию переводчика. Её надо написать, даже если ничего такого никто и не планировал.

Лично я поставил переводчику минус в карму. Чего не делал наверно никогда раньше. Потому что это за гранью добра и зла
Я ни в коем случае не пытаюсь оправдать автора перевода. Поймите меня правильно. Мне просто интересны его мотивы в конкретном данном случае, т.к. конкретно этот перевод не вписывается в общую картину от слова совсем. У переводчика реально много статей на хабре. Все не читал, но вроде рейтинг у него даже после такой статьи не просел.
Обычно когда авторы переводов косячат — они в комментах активно соглашаются с замечаниями, правят на ходу статью. А тут — тишина.

Рейтинг у автора упал пунктов на 20. Что касается появления в кометариях — вы посмотрите — часто он вообще бывает к коментариях к своим статьям.

Haxe еще не считается языком программирования?
А на мой взгляд, необходимо указывать недостатки только в актуальных версиях языков.
Я на самом деле читал статью только про PHP и Java и могу назвать необоснованными аргументы, помеченные как Исправлено в PHP 7, и тем более Исправлено в PHP 5, который был выпущен в 2004 (!) году
К критике Java, претензий меньше, хотя так же считаю несерьезными обвинения в том, что уже исправлено
Все это не есть недостатки, это просто фичи.
Баг Хабра: если ссылка-якорь в посте до ката, то с главной (топа) она работает некорректно (точнее, не работает)
По-моему наибольшая ценность этой статьи заключается в феерическом переводе. Спасибо, подняли настроение всему офису.
Проблема отступов — обычно её называют «проблемой пробелов»

Да заебали уже. Нет никакой проблемы отступов.

Проблема в пробелах — это пробел в проблеме.

Ещё из очаровательного.

VBA: Поддерживает GoTo.
Python: Прерывание или продолжение по метке отсутствуют.

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

И вообще, по python (а имею сопоставимый объём опыта и в нём, и в php и в js) такое ощущение, что автор к трём-четырём реально перечисленным проблемам высосал из пальца ещё десяток, основанных на вкусовых предпочтениях, чтобы никому не показалось, что python действительно хороший язык. По он php тоже нафантазировал достаточно много, раздув список реальных проблем раза в два. Насчёт остальных языков не скажу, т.к. использовал их мельком.
Ваш перевод — отстой! Пожалуйста, прекратите свою деятельность на хабре… По крайней мере в таком виде (я имею в виду, что видел ваши достаточно сносные переводы).
Нет делегатов; каждый раз, когда нужен указатель на функцию, приходится реализовывать заводскую разработку


«Заводскую разработку»? Нет, вы это серьезно?!
Начал читать про Javascript и Ruby, многое слышал.

Когда дошел до С, начал что-то подозревать.
Массивы переменной длины, как правило, помещаются в стек, а это означает, что передача при слишком большом размере небезопасна

Где автор видел, что массивы переменной длинны помещаются в стек? Как потом менеджить указатель на этот самый стек? (Певый вопрос из многих, который пришел в голову)

Когда дошел до Rust, понял, что половина текста написана в минуты отчаяния. Часть про Rust уж точно.
mut означает исключительный, а не изменчивый (mutable). &Mutex означает изменчивый (mutable), а &mut str — неизменяемый (immutable)

Ни одно из вышеперечисленных предложений не верно.

Изменить файл? Потребуется перекомпилировать всю вашу библиотеку. Кстати — rustc работает медленно.

Исправленно.

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

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

Нет пространства имён в поставке.

В какой поставке? Есть пространства имен. В Rust они называются modules и crates.

Поскольку в поставке нет никаких попыток кэширования артефактов компилятора, то вы компилируете каждую раздутую библиотеку каждый раз, когда создаёте новый проект. Я уже говорил, что rustc работает медленно?

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

Про многие мелкие недочеты уже промолчую
Не факт, что много «устаревших копий кольца» это плохо (сильно смеюсь). Что переводчик тут имел в виду, так и не понял.
One ring to rule them all, one ring to find them,
One ring to bring them all and in the darkness bind them.
Где автор видел, что массивы переменной длинны помещаются в стек? Как потом менеджить указатель на этот самый стек? (Певый вопрос из многих, который пришел в голову)

Для этих целей существует регистры esp/rsp и ebp/rbp. С одним регистром это и правда было бы трудно, но два позволяют проворачивать такие трюки.


А еще есть такая функция как alloca

Функция есть, но это массивы «статической» длинны, потому однажды выделив память, известен ее размер. Во-вторых, его никак не «передать небезопасно», потому что передать можно только указатель на массив. В-третих, для них заранне известен размер, а не как у автора.

А как еще вы предлагаете перевести Variable-length arrays (VLA)?

А, извините, неправильно трактовал написаное. Посыпаю голову пеплом. В любом случае фразы:
что передача при слишком большом размере небезопасна

и
Нет никакого способа узнать, что ваше назначение является слишком большим

сомнительны.
Для этих целей существует регистры esp/rsp и ebp/rbp.

Не нашел их среди своих r1-r12, sp, lr и pc, к сожалению. /irony

Нет, sp/fp (r13/r11).
ip (r12) — это scratch register.
Вариантность символов чрезвычайно раздражает.


Должно быть «изменение сигилов чрезвычайно раздражает».

Точечное представление для методов, свойств и т.д. является хорошим делом


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

«unless» («пока не»)


unless — это «если не».
«Пока не» тоже допустимо в некоторых случаях.

Что-то мне не удалось нагуглить случаев, когда unless является частью оператора цикла.

Вот, пожалуйста.

$not_finished=True;
while (1>0)
{ 
# Do iteration, possibly setting $not_finished to False;
break unless $not_finished;
}

"Продолжить если не $finished"


От того что телом цикла стел оператор continue — unless не перестает быть условным оператором.

unless, until — какая разница ,)

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

Либо слишком мало, ведь у круга бесконечное количество углов!

Lisp — он идеален… только скобочек много, но кто скажет это отстой тот просто ничего не смыслит в списках :)

Про питон — половина просто зашоренность автора, четверть — притянутые за уши кейсы, еще четверть реально неудобные вещи, но не криминальные. А вот про пару реально отстойных моментов — не упомянуто.
>Про питон — половина просто зашоренность автора
Кстати да. Более того, пример с отступами и вложенными if/else я бы использовал в качестве аргумента «за» отступы вместо {}
Про питон — половина просто зашоренность автора, четверть — притянутые за уши кейсы, еще четверть реально неудобные вещи, но не криминальные. А вот про пару реально отстойных моментов — не упомянуто.

Это верно для всех перечисленных языков :)

Особенно в части перевода.
ДРАКОН, Blueprint, LabVIEW…
UFO just landed and posted this here
Неполная встроенная поддержка комплексных чисел: как (-1)**(0.5), так и pow(-1, 0.5) выдают ошибку вместо возврата 0+1j.

>>> (-1)**(0.5)
(6.123233995736766e-17+1j)
>>> pow(-1, 0.5)
(6.123233995736766e-17+1j)
Отвечу на некоторые претензии к Lua.

> Объявление переменной является глобальным по умолчанию
> Разыменование на несуществующем ключе возвращает ноль вместо ошибки.
Все же не ноль, а nil, который изначально подразумевает отсутствие значения. Если хочется чуть больше безопасности можно повесить метатаблицу на _G или использовать существующий модуль — http://www.lua.org/extras/5.2/strict.lua.

> Невозможно выполнять перебор varargs
Возможно с помощью функции select.

> Операторы отличаются от выражений, а выражения не могут существовать вне операторов
И слава Богу. Выражения вне оператора присваивания словно приглашают создавать перегрузкой операторов стратегические ракеты класса космос-нога.
А вот D — имба язык, и к нему 0 придирок! :)
Спасибо за обзор. Со многим согласен.
Замечания по Java:
>> Нет ключевого слова var для предполагаемых локальных типов (как в C#).
Появится в java 10
http://openjdk.java.net/jeps/286

>> Программный интерфейс данных (Date API) считается устаревшим, но до сих пор повсеместно используется. >> Плана замены нет.
В java8 появилось LocalDate, LocalTime, LocalDateTime. Фактически это API yoda time
http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html
Про VBA

> • Индексы массива начинаются с нуля, но индексы коллекции — с единицы.
Вообще не критично. Из соображений унификации можно указать OPTION BASE 1

>• У классов нет конструкторов, которые могут принять аргументы.
>• Невозможно перегрузить методы.
>• Нет наследования.

VBA — это Visual Basic for Application
Изначально предназначен для работы в средах приложений, перенасыщенных объектами — Excel, AutoCAD… С объектами и их свойствами можно делать многое, наворачивать еще и свой объектный слой — достаточно сложно и не нужно. Мне вполне хватает процедурных возможностей. Классы конечно создаю, особенно «наблюдатели»… with Events — но это не более 5% кода.
И в дополнение про отсутствие какого-либо наследования — если делать акцент на таких аспектах, то тогда и отсутствие множественного наследования является признаком «отстойности» многих языков.

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

> • `OnError Resume Next` — Yeah… Происходит именно то, что вы читаете. Обнаружена ошибка? Нет проблемы! Просто продолжайте упираться и продвигаться вперёд в следующей строке.

Именно так! — Продвиньтесь к следующей строке, в которой легко и просто разберитесь с типом возникшей ошибки. Как я указал выше, в среде приложений мы работаем с невероятным количеством объектов, каждый из которых имеет множество свойств. Т.к. в средах этих же приложений, как ни странно, кроме наших программ работают еще и пользователи, то фактическое (в конкретный момент времени) состояние объектов может резко отличаться от требуемого — нет нужной рабочей книги, или она есть, но почему-то защищена, или вместо ожидаемого активного Worksheet активным является какой-то другой Sheet… и еще масса нюансов. И что плохого если я могу поэтапно анализировать состояние среды, регламентно реагируя на ошибки сразу в этих же фрагментах кода, не перескакивая в обработчики ошибок? За OnError Resume Next разработчикам нужно нобелевскую премию выписать!

>• Свойства по умолчанию.

1) Насколько я понимаю, слегка упрощает механизм автоматизированной записи действий пользователя и написание коротких простых макросов;
2) Не используйте свойства по умолчанию в VBA-программах более 15 строк;
3) На выработку этого устойчивого навыка мне потребовалось 120 секунд, 25 лет назад — в чем проблема?

>Приведённые ниже две строки означают не одно и то же.
Dim myRange As Variant
myRange = Range(«A1»)
Set myRange = Range(«A1»)

Не используйте тип Variant там, где тип объекта очевиден — а это 99,6% кода. Знайте, что осмысленное использование Variant экономит десятки строк кода — например, Activesheet может быть как Worksheet так и какой-то другой Sheet — изначальное присвоение переменной типа Variant затем позволяет одной строкой выяснить тип активного листа Excel и понять, можно ли двигаться дальше или нужно обработать ошибку.

C#. Невозможно выполнить какие-либо операции (даже простейшие арифметические) с объектами внутри обобщённого метода (например, T plus<T>(T t1, T t2) { return t1+t2; }

В .NET 7 эту проблему, наконец-то, разрешили.

Articles