Re[79]: Когда это наконец станет defined behavior?
От: · Великобритания  
Дата: 17.05.23 12:52
Оценка:
Здравствуйте, so5team, Вы писали:

s>>> В том, что в C++ есть возможность написать const для объекта. В Java нет.

S>·>В java другие подходы для реализации ровно того же.
S>Как будто с вами кто-то спорил на тему того такие же они или нет. Мои тезисы касательно Java таковы:
S>a) требуется вводить новую сущность, интерфейс, который предоставляет read-only доступ к объекту и это не есть хорошо, т.к. это дополнительная (и по сути не нужная) сущность в программе, с которой программисту нужно иметь дело.
Нет _новой_ сущности. Модификатор тоже неявно создаёт новый тип. Вместо неявного типа "const X" делается явный тип "ConstX".

S>Ваши возражения (насколько я их запомнил):

S>- то, что дополнительная -- не проблема;
Нет. Главное возражение — что сущность не дополнительная, а ровно та же, но выраженная другим способом через другие средства ЯП.
Проблема const — это интрузивность. Это усложняет и так непростую систему типов. С другой стороны это частный случай определённого аспекта дизайна.

S>- создавать ее дешево за счет помощи IDE.

Это да. Если набирать всё дело в notepad, то придётся нажать больше кнопок. Тут согласен. Но я давно не набирал код в notepad. Поэтому проблема некритичная совершенно.

S>b) в реализации этой новой сущности со стороны языка нет никакого контроля за тем, выполняются ли там модификации состояния объекта или нет.

S>Ваши возражения (насколько я их запомнил):
S>- такого не бывает (у вас по крайней мере);
Мы рассмотрели твой пример с твоим chunk и там выяснилось, что const даже если бы и был, в java некуда было бы пристроить. Он там просто не нужен.

S>- есть final и records.

Верно. И они относятся к более полезной идее — иммутабельность, а не константность.

S>Мой контр-тезис по поводу второго возражения: final бесполезен если поле не value type, в общем, это для частных случаев, а не защита от модификации в общем.

Ровно настолько же бесполезен, как и const :
struct C
{
    std::string *s = new std::string("hi");
    const std::string &val() const {return *s;}
};

int main()
{
    const C c;
    std::cout << c.val() << std::endl;
    *c.s = "bye";
    std::cout << c.val() << std::endl;
}

В чём разница-то с этим кодом
Автор: so5team
Дата: 12.05.23
, который ты жаве ставил в упрёк? Объект константный, а "модифицировать в общем" можно!

Мой тезис в том, что концепция const и уж тем более реализованная как в плюсах — очень спорной полезности. И в других ЯП уж точно не нужна. У меня есть даже сомнения в её полезности в самих плюсах, но уже не считаю себя экспертом по плюсам, т.к. уж лет 10 на нём не писал.

S>Соответственно, я просто заключаю, что в C++ с const есть больше помощи со стороны собственно языка, чем в Java. Что хорошо и, как по мне, сильно лучше, чем в Java.

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

S>При этом я нигде не утверждал, что подход из C++ самый лучший. Напротив, говорил, что в Rust и D пошли еще дальше, и это хорошо, т.к. там смогли учесть опыт C++.

А некоторые пошли другим путём и выкинули константность вообще. Чем плохо-то?

s>>> Ок что? Где цитата, которая подтверждает, что я что-то утверждал или "что сел в лужу с ссылками и указателями"?

S>Таки что с цитатами?
Не цитаты, а в целом тезисы которые ты выдвигаешь. Константность ссылкок-указателей элементарно заменяется интерфейсом, тут вообще неясно почему ты задал такой вопрос изначально. А константность объектов, на которую ты перешел — не заслуга компилятора, а средство, которое требует усилия и опыт программиста.

S>·>Попробуйте этом коде просто так модифицировать v.

S>Т.е. const в C++ настолько плох, что вы не смогли модифицировать C++ный пример и были вынуждены переводить стрелки на Java.
Он плох в том, что он просто нахрен не нужен как лишняя фича ЯП, т.к. ровно то же делается на уже существующей концепции интерфейсов, которая более мощная и универсальная, делает const ссылкок-указателей тупо ненужным.

s>>> ·>У тебя опять память подводит. Есть final, record и даже sealed интерфейсы.

s>>> Ну и как с помощью этого всего сделать из HashMap неизменяемый HashMap? Ну вот был HashMap, требуется сделать так, чтобы его модифицировать нельзя было.
S>·>Если в типе изначально не предусмотрена константность (не предусмотрены методы с const), то ты нихрена не сделаешь.
S>Я все равно смогу объявить экземпляр этого типа как const. Насколько это будет полезно (возможно и будет, т.к. хотя бы указатели на него можно будет использовать) -- это второй вопрос. Но я любой тип могу использовать как const. И это делается средствами языка, а не приседаниями разработчика.
Для тебя второй вопрос. Для меня — основной. Накой переусложнять ЯП, ради сомнительной околонулевой полезности.

S>В этом так же принципиальное отличие C++ от Java. В лучшую сторону.

Лучшесть — понятие относительное. Java нарочно делали языком простым, как можно проще, но не проще. Если тебе надо кучу фич и концептов, бери какую-нибудь Скалу, на той же платформе.

S>·>В HashMap не предусмотрена константность.

S>О том и речь.
Ну тип такой. В чём возражение-то? В плюсах тоже можно написать тип и не предусмотреть константность. Это как-то повлияет на хорошесть плюсов?

S>·>Однако, объект HashMap можно сделать неизменяемым, например, с помощью Collections.unmodifiableMap.

S>И в compile-time никакой помощи от компилятора не будет.
S>Но да, она же вам и не нужна, проссыте великодушно.
Это особенности реализации конкретного api. Можно найти или реализовать свою библиотеку коллекций, если очень так хочется.
Скажем, в том же C# (который очень похож на java) сделали то что ты хочешь без всяких const, в фреймворке есть набор RO-интерфейсов. Например, List так же реализует IReadOnlyList. А так же есть ImmutableList. Т.е. и иммутабельность есть, и константность, и никакой встроенный в ЯП const нафиг не сдался. Т.е. это вопрос дизайна API и конкретных типов, а не наличия определённой фичи в ЯП.

S>·>Попробуйте заставить компилятор принять у вас такой код.

S>Т.е. const в C++ настолько плох, что вы не смогли модифицировать C++ный пример и были вынуждены переводить стрелки на Java.
Я не понял как ты хотел чтобы я что-то модифицировал и с какой целью. Я привёл как аналгичный трюк const достигается без const, без использования специальных фич ЯП.

S>И это не говоря о том, что вообще-то в C++ vector остается vector-ом с его методами data, at и operator(), тогда как приводя вектор к Iterable в Java вы теряете часть доступных методов.

Это недостаток collections api в jdk, а не Java. Впрочем достать произвольный элемент всё ещё можно через skip/limit. В том же шарпе такой проблемы нет и const нет. Т.е. для реализации того что ты хочешь — const не нужен. Это надо блин просто взять и реализовать.

s>>> Хде, хде, блин, этот опровергающий пример? Пока ни одного не было. Были примеры с наличием const-ссылок, но отсутствием const-объектов.

S>·>Именно. И это никак компилятором не проверяется. Всё на честном слове — не забыл (не смог, т.к. его надо было собрать из кусочков, например) поставить const на объекте — сработает. Не смог — не сработает. И компилятор будет молчать.
S>Мне что, нужно в очередной раз повторить, что const&/const* в C++ ничего не говорит о константности исходного объекта?
Ну да. И это — проблема.

S>const&/const* имеют к константности только то отношение, что это единственный легальный способ ссылаться на const-объект. И если нам нужна именно константность, то говорить следует именно о const для объектов, а не о const&/const*.

Вопрос-то — а нужна ли нам константность объектов в принципе. Я считаю, что иммутабельность нужна, константность — нет. И это делается через List/ImmutableList/IReadOnlyList без каких-либо дополнительных фич в ЯП.

S>Примеры когда const для объекта не обеспечивает константность приводить можно и это не сложно (даже без mutable). Кроме того, в C++ с const связаны и другие проблемы (контроль времени жизни, к примеру).

S>Однако, даже по совокупности, лично я никак не могу согласиться с тем, что от const в C++ мало толку.
Возможно, пусть так. Однако твой вопрос был о толке const в других ЯП.

S>·>Описывать const-методы программист тоже должен делать вручную. Т.е. решить какие вещи в данном типе могут, а какие не могут быть const.

S>Да, это часть работы по проектированию типа.
Именно. По сути ты проектируешь пару типов — const/non-const. Всё то же, никаких дополнительных сущностей, как ты заявил выше.

S>·> Вопрос был: "как же константность объекта там _гарантированно_ появится?" Откуда в данной строчке будет гарантированно стоять модификатор const?

S>Для клинических идиотов: не смысла обсуждать вероятность того, что сделает, а чего не сделает пользователь когда речь заходит о возможностях языка. Зато смысл есть обсуждать последствия того, что сделал или не сделал пользователь.
Вопрос стоял в том как же с помощью const _гарантированно_ защитить данные, которые передаются другим тредам. Как выяснилось — да никак, это лежит на совести и внимательности программиста: создал и передал константный объект — молодец, создал неконстантный объект, но не модифицировал — тоже молодец, а помодицифировал, ну сам виноват. Помощь от компилятора — нулевая. Полный эквивалент List+IReadOnlyList.
Решение только — использовать иммутабельные данные: если другой тред берёт тип ImmutableList, то у тебя 100% гарантия, проверяемая компилятором, что данные не поменяются. Ну или borrow checker.
Т.е. const объект не даёт никакой проверяемой компилятором защиты и в этом случае, только мамойклянус работает.

S>Вот, например, почему-то никто не стремится обсуждать вероятность того, что пользователь ошибется при вычислении значения i перед выполнением операции v[i]. И это правильно, т.к. вероятность совершения ошибки таки есть. Поэтому разумнее сосредоточиться на обсуждении последствий. И в C++ они фатальнее, чем в Java. В этом важное отличие между языками.

А мы не о вероятностях. А о том, что именно даёт конкретная фича ЯП. Пока выяснилось, что константный объект даёт лишь локальную защиту локальной переменной внутри метода. И собственно всё. Что можно сделать, например, вот так:
IReadOnlyList myConstList = new List(...);


S>Аналогично и с const. Если программист не объявил объект как const, то константности у него нет. Поэтому и нет смысла обсуждать какие-то гарантии со стороны компилятора, ибо их нет.

Моё мнение — практической пользы — маловато будет. Пусть это останется вкусовыми предпочтениями.

S>А вот если программист таки const использовал, вот тогда есть смысл рассуждать о том, что гарантирует компилятор, что не гарантирует и насколько этому const-у можно доверять вообще.

В чём разница-то с правильным выбором типов List/ImmutableList/IReadOnlyList?

S>Так что вопрос "как же константность объекта там _гарантированно_ появится?" идет прямиком в /dev/null как в силу своего идиотизма, так и из-за бесполезности.

Ну вот с иммутабельностью этот вопрос почему-то даже не появляется, внезапно. Иммутабельность — полезный концепт, т.к. действительно даёт полезные гарантии.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 17.05.2023 12:53 · . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.