Здравствуйте, ·, Вы писали:
s>> Или стокгольмский синдром ·>Ага, но я не страдаю, я наслаждаюсь.
А это одно из его проявлений
s>> А интерфейсы откуда берутся? Ладно бы Java позволяла отдельно определить тип, отдельно интерфейсы, да еще чтобы можно было автоматически объект привести к нужному интерфейсу (что-то вроде того, что в Go сделано). А то нужно сперва сделать интерфейс, потом в типе его имплементировать. ·>Просто другой mind-set.
Ну да, простой константности нет, приходится выкручиваться по другому.
·>Не знаю что именно ты считаешь нужно держать в голове.
Представления о типах еще до того, как они были реализованы. И взаимоотношения между типами когда они уже были реализованы.
·>Иммутабельный тип имеет final-поля, которые нельзя изменить, нет никакого механизма снять final. А так же тип обычно тоже final (т.е. нельзя унаследоваться и переопределить поведение).
Грубо говоря:
class Data {
public void change() {...}
...
}
class ImmutableData final {
public final Data data = new Data(...);
...
}
...
final ImmutableData immutableData = new ImmutableData(...);
Если речь про это, то разве в Java нельзя сделать вызов immutableData.data.change()?
·>Константность это немного о другом. Это когда у тебя есть некий объект и в одном месте ты можешь его менять его состояние, а в другом — не можешь.
Это только часть проблемы.
·>Если не зацикливаться на конкретно "менять", а обобщить до "совершать некие операции", то интерфейсы — оно и есть.
Опять приходим к тому, что в Java от компилятора в этом нет никакой помощи. Тогда как в более продвинутых языках (и речь не только про C++) иммутабельность/константность -- это одна из мега-фич, как и контроль за этим со стороны компилятора.
s>>Приходится городить интерфейсы и радоваться тому, что IDE это упрощает. ·>Ты так говоришь, как будто это что-то плохое
Да, это ущербность. К которой можно и привыкнуть, и научиться ее преодолевать с помощью IDE. Но ущербностью она быть не перестает.
Re[38]: Когда это наконец станет defined behavior?
Здравствуйте, so5team, Вы писали:
s> ·>Ага, но я не страдаю, я наслаждаюсь. s> А это одно из его проявлений
Я могу бросить!! В любой момент!!!
s> ·>Просто другой mind-set. s> Ну да, простой константности нет, приходится выкручиваться по другому.
Просто константность — невеликая проблема.
s> ·>Не знаю что именно ты считаешь нужно держать в голове. s> Представления о типах еще до того, как они были реализованы. И взаимоотношения между типами когда они уже были реализованы.
Это mind-set какого-то нотепада. Есть же рефакторинги. "Выделить интерфейс", "переместить метод в потомка|предка" и т.п.
Не надо продумывать всё досконально и не иметь права на ошибку. Если что-то не так, можно быстро исправить.
s> Если речь про это, то разве в Java нельзя сделать вызов immutableData.data.change()?
Можно. Но
Во-первых, иммутабельный тип по правилам собирается из иммутабельных. Либо держит мутабельные вещи у себя внутри и наружу не отдаёт.
Во-вторых, иногда нужно. Например этот самый change() может быть сборщиком статистики или логов, такое надо по дизайну. Перезаворачивать всё в mutable — тоже так себе.
В-третьих, ещё ты забыл вариант, когда data заходит внутрь ImmutableData через конструктор. От такого и const не поможет.
В-четвёртых, иммутабельность и константность всё-таки разные вещи.
s> ·>Константность это немного о другом. Это когда у тебя есть некий объект и в одном месте ты можешь его менять его состояние, а в другом — не можешь. s> Это только часть проблемы.
А другая часть?
s> ·>Если не зацикливаться на конкретно "менять", а обобщить до "совершать некие операции", то интерфейсы — оно и есть. s> Опять приходим к тому, что в Java от компилятора в этом нет никакой помощи. Тогда как в более продвинутых языках (и речь не только про C++) иммутабельность/константность -- это одна из мега-фич, как и контроль за этим со стороны компилятора.
Если её можно снимать, то смысл как-то теряется. А без её снятия не сделаешь некоторые полезные вещи.
s> ·>Ты так говоришь, как будто это что-то плохое s> Да, это ущербность. К которой можно и привыкнуть, и научиться ее преодолевать с помощью IDE. Но ущербностью она быть не перестает.
Просто это такая мелочь, что вообще не ощущается как проблема. Нечего преодолевать собственно.
А IDE всё равно будет. Т.к. помощь IDE не только в этом, а ещё в очень многом.
Здравствуйте, B0FEE664, Вы писали:
BFE>В C тоже есть assert'ы
Почти assert-ы но только помимо проверок они могли-бы компилятору помогать с оптимизацией. assert сам по себе просто проверка некоторого условия.
Вот смотрите вы хотите передать объект в функцию и хотите что бы выполнялось какое-то условие, но и функция может требовать соблюдение определённых условий для своей работы.
И если они не совместимы можно предупреждать или делать переходники.
Assert-ы не позволяют эти данные использовать, только проверить на конкретных данных. Эта невозможность порождает всякие методики тестирования типа fuzzing
Re[52]: Когда это наконец станет defined behavior?
Здравствуйте, ·, Вы писали:
·>Я могу бросить!! В любой момент!!!
Конечно, я сам так делал несколько раз
·>Просто константность — невеликая проблема.
Наличие константности -- это вообще благо. А вот отсутствие...
К сожалению, в C++ константность недостаточно строгая
·>Не надо продумывать всё досконально и не иметь права на ошибку. Если что-то не так, можно быстро исправить.
"фигак-фигак-и-в-продакшен" mind-set detected
s>> Если речь про это, то разве в Java нельзя сделать вызов immutableData.data.change()? ·>Можно.
О том и речь, что неизменяемость данных в Java -- это очень непростой вопрос. И Java точно не тот язык, который следовало бы приводить в пример.
·>В-четвёртых, иммутабельность и константность всё-таки разные вещи.
В C++ речь может идти только о константности, которая в большом количестве случаев тождественна иммутабельности, но есть нюансы...
s>> ·>Константность это немного о другом. Это когда у тебя есть некий объект и в одном месте ты можешь его менять его состояние, а в другом — не можешь. s>> Это только часть проблемы. ·>А другая часть?
Что константность может быть как раз иммутабельностью. Грубо говоря:
const std::string hello{ "Hello, World" };
и у нас реально константный объект.
В C++ не хватает возможности при передаче по константной ссылке/указателю сказать потребителю, что он (потребитель) имеет дело именно с иммутабельным значением. Из-за этого у потребителя есть большой вопрос: а насколько он может доверять полученной ссылке (указателю). Вот тут-то основные проблемы и появляются.
·>Если её можно снимать, то смысл как-то теряется. А без её снятия не сделаешь некоторые полезные вещи.
Из моего опыта: применение const_cast _всегда_ указывает на наличие проблем. Это костыль, появление которого в коде означает, что где-то что-то пора поменять.
·>А IDE всё равно будет. Т.к. помощь IDE не только в этом, а ещё в очень многом.
Охотно верю. Но когда без IDE языком становится пользоваться невозможно (как в случае с Java), то с этим языком что-то сильно не так.
Re[46]: Когда это наконец станет defined behavior?
S>И да, в C++ сейчас больше чем два варианта const|non-const: &, const &, && и, для ценителей, const && S>Правда, в C++23 вроде как это дело поправят, но как зачастую бывает в C++, через жопу.
Там шо, введут
&&&
?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[40]: Когда это наконец станет defined behavior?
Здравствуйте, kov_serg, Вы писали:
BFE>>В C тоже есть assert'ы _>Почти assert-ы но только помимо проверок они могли-бы компилятору помогать с оптимизацией. assert сам по себе просто проверка некоторого условия. _>Вот смотрите вы хотите передать объект в функцию и хотите что бы выполнялось какое-то условие, но и функция может требовать соблюдение определённых условий для своей работы. _>И если они не совместимы можно предупреждать или делать переходники. _>Assert-ы не позволяют эти данные использовать, только проверить на конкретных данных. Эта невозможность порождает всякие методики тестирования типа fuzzing
Не понятно.
Хотите что-то проверить компилятором, то есть static_assert.
Хотите переходники, то просто пишите if (условие) goto
Какая разница, напишите вы эти условия в секциях in/out или просто в коде?
Всё равно: приходящие из внешнего мира данные вы никак не проверите, кроме как в run-тайме.
И каждый день — без права на ошибку...
Re[44]: Когда это наконец станет defined behavior?
Здравствуйте, kov_serg, Вы писали:
_>Разница огромна. Вместо дополнительного типа у нас требования (ограничения) которые должна соблюдать функция. Они могут описывать разные виды ограничений. _>Например: _>
void do_something(int o[3]) where o[1] is immutable; -- запрещено менять o[1]
И что будет если:
void do_something(int o[3]) where o[1] is immutable // -- запрещено менять o[1]
{
o[rand() % 3] = 1;
}
?
И каждый день — без права на ошибку...
Re[50]: Когда это наконец станет defined behavior?
Здравствуйте, T4r4sB, Вы писали:
TB> ·>Там где это действительно нужно, всегда можно сделать иммутабельный тип. TB> Как жаба следит чтоб ты не менял ключи хешмап?
Не следит. Это в принципе невозможно по крайней мере в подавляющем числе ЯП. Что если у тебя ключ get_current_time()?
Здравствуйте, so5team, Вы писали:
s> ·>Я могу бросить!! В любой момент!!! s> Конечно, я сам так делал несколько раз
А на людей я и не бросаюсь.
s> ·>Просто константность — невеликая проблема. s> Наличие константности -- это вообще благо. А вот отсутствие...
Хаскель же уж если так хочется. А то ведь смотря какая константность:
s> К сожалению, в C++ константность недостаточно строгая
Именно.
s> ·>Не надо продумывать всё досконально и не иметь права на ошибку. Если что-то не так, можно быстро исправить. s> "фигак-фигак-и-в-продакшен" mind-set detected
Не совсем. YAGNI же.
s> ·>Можно. s> О том и речь, что неизменяемость данных в Java -- это очень непростой вопрос. И Java точно не тот язык, который следовало бы приводить в пример.
Это не в java, а в программировании вообще.
Впрочем, если так хочется неизменяемости, можно взять Скалу на той же платформе. Но, честно говоря, меня оно не впечатлило. Да, данные иммутабельы, но просто меняется стиль работы с ними. Выстраиваются цепочки созданий копий данных с изменениями и в итоге изменения-то есть, и все проблемы с ними связанные, но писать код сложнее стало.
Было
var data = ...
modifyX(data);
modifyY(data);
стало
var data = ...
data = modifyX(data);
data = modifyY(data);
а проблемы те же.
s> В C++ речь может идти только о константности, которая в большом количестве случаев тождественна иммутабельности, но есть нюансы...
Нюансы, да.
s> ·>А другая часть?
s> Что константность может быть как раз иммутабельностью. Грубо говоря: s>
s> const std::string hello{ "Hello, World" };
s>
s> и у нас реально константный объект.
Он константный лишь потому, что так говорит Стандарт про std::string. А если это какой-то левый тип, там внезапно зависимость от статик переменной и приплыли.
А так в java то же самое final String hello = "Hello, World" реально иммутабельный объект в константной переменной.
s> В C++ не хватает возможности при передаче по константной ссылке/указателю сказать потребителю, что он (потребитель) имеет дело именно с иммутабельным значением. Из-за этого у потребителя есть большой вопрос: а насколько он может доверять полученной ссылке (указателю). Вот тут-то основные проблемы и появляются.
В java делают defensive copy, как правило.
s> ·>Если её можно снимать, то смысл как-то теряется. А без её снятия не сделаешь некоторые полезные вещи. s> Из моего опыта: применение const_cast _всегда_ указывает на наличие проблем. Это костыль, появление которого в коде означает, что где-то что-то пора поменять.
Вот в скажем в том же String — есть поле hashCode, которое неконстантное. При первом вызове метода хеш-код считается и записывается в эту переменную. Последующие вызовы используют предыдущее значение. Так что формально внутреннее состояние объекта неконстантно, но внешне объект всё ещё иммутабельный.
s> ·>А IDE всё равно будет. Т.к. помощь IDE не только в этом, а ещё в очень многом. s> Охотно верю. Но когда без IDE языком становится пользоваться невозможно (как в случае с Java), то с этим языком что-то сильно не так.
Или наоборот — сильно так. ЯП умудряется быть не только простым для человека, но и поддаётся автоматической обработке.
Иначе тебе приходится очень аккуратно думать как назвать каждую переменную и функцию и т.п. Без рефакторингов это будет дорогой ошибкой, если придётся потом что-то поменять.
Может быть это важно для написания каких-то общеиспользуемых библиотек, но в обычных аппликухах это не так.
Здравствуйте, T4r4sB, Вы писали:
S>>И да, в C++ сейчас больше чем два варианта const|non-const: &, const &, && и, для ценителей, const && S>>Правда, в C++23 вроде как это дело поправят, но как зачастую бывает в C++, через жопу.
TB>Там шо, введут TB>
Здравствуйте, T4r4sB, Вы писали:
TB> ·>Не следит. Это в принципе невозможно по крайней мере в подавляющем числе ЯП. Что если у тебя ключ get_current_time()? TB> В С++ есть const. Этого достаточно. Написать const_cast можно, но случайно — нет.
Не понял, ты же в мапу ключ кладёшь снаружи. Или мапа копию делает?
Скажем, ключом в мапе может быть массив из миллиона элементов... Дальше продолжать?
Не говоря уж о том, что может быть зависимость от статической переменной.
Здравствуйте, ·, Вы писали:
·>Не понял, ты же в мапу ключ кладёшь снаружи. Или мапа копию делает?
Копию, конечно.
·>Скажем, ключом в мапе может быть массив из миллиона элементов... Дальше продолжать?
Мув-копию.
Когда жабисты рассказывают о крестах, иногда такой кринж
·>Не говоря уж о том, что может быть зависимость от статической переменной.
Ну ещё можно хреново написать хеш-функцию, (чтоб она зависела от таймера например), тоже мапа поломается. Только хеш-функцию пишется один раз, а вот итерация по мапе делается регулярно и там проследить за кривыми руками кодера сложнее.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[45]: Когда это наконец станет defined behavior?
Здравствуйте, T4r4sB, Вы писали:
TB> ·>Не понял, ты же в мапу ключ кладёшь снаружи. Или мапа копию делает? TB> Копию, конечно.
А если указатель?
TB> ·>Скажем, ключом в мапе может быть массив из миллиона элементов... Дальше продолжать? TB> Мув-копию.
А если массив является ключом в двух разных мапах?
TB> Когда жабисты рассказывают о крестах, иногда такой кринж
Ты ещё не слушал плюсовиков, которые рассуждают о жабе.
TB> ·>Не говоря уж о том, что может быть зависимость от статической переменной. TB> Ну ещё можно хреново написать хеш-функцию, (чтоб она зависела от таймера например), тоже мапа поломается. Только хеш-функцию пишется один раз,
К сожалению нет. Класс ключа может меняться, добавляться новые поля, например.
TB> а вот итерация по мапе делается регулярно и там проследить за кривыми руками кодера сложнее.
Короче, может и есть какие-то средства, работающие в каких-то сценариях, никакой гарантии нет.
Здравствуйте, ·, Вы писали:
s>> ·>Просто константность — невеликая проблема. s>> Наличие константности -- это вообще благо. А вот отсутствие... ·>Хаскель же уж если так хочется.
Haskell или OCaml хорошие примеры, но там GC, это другая область. Меня радует, что в Rust-е сделали константность. Причем предположу, что там за счет borrow checker-а похожая на C++ модель константности работает лучше, чем в C++ (но утверждать не могу, дальше hello-world-ов у меня с Rust-ом не зашло).
s>> ·>Не надо продумывать всё досконально и не иметь права на ошибку. Если что-то не так, можно быстро исправить. s>> "фигак-фигак-и-в-продакшен" mind-set detected ·>Не совсем. YAGNI же.
C++ более требовательный язык и задачи на нем простотой не отличаются, так что здесь "не совсем" и "yagni" имеют другой привкус.
·>Это не в java, а в программировании вообще.
"Отучаемся говорить за всех" (с)
s>> Что константность может быть как раз иммутабельностью. Грубо говоря: s>>
s>> и у нас реально константный объект. ·>Он константный лишь потому, что так говорит Стандарт про std::string.
Замените std::string на любой пользовательский тип и вы обнаружите, что для const объекта компилятор разрешает вызывать только const-методы. А в const-методах нельзя менять поля объекта.
И это изкаропки и бесплатно.
·>А если это какой-то левый тип, там внезапно зависимость от статик переменной и приплыли.
Как приплыли, куда приплыли, ничего не понятно.
·>А так в java то же самое final String hello = "Hello, World" реально иммутабельный объект в константной переменной.
Так это у вас безусловный рефлекс на то, что в Java String -- это иммутабельная строка, вот вам и кажется, что вы приводите аналогичный пример. Замените std::string на std::vector из std::queue и ничего не поменяется. В отличии от Java.
·>В java делают defensive copy, как правило.
Так память же не ресурс!
·>Вот в скажем в том же String — есть поле hashCode, которое неконстантное. При первом вызове метода хеш-код считается и записывается в эту переменную. Последующие вызовы используют предыдущее значение. Так что формально внутреннее состояние объекта неконстантно, но внешне объект всё ещё иммутабельный.
В C++ для этих целей есть mutable, который устраняет надобность во многих const_cast. А вот когда в коде появляется const_cast, то это уже признак наличия какого-то костыля.
·>Или наоборот — сильно так.
Не так. Есть языки посложнее Java (или C#), которые десятилетиями живут без IDE уровня IDEA или VisualStudio и это никому не мешает.
·>Иначе тебе приходится очень аккуратно думать как назвать каждую переменную и функцию и т.п.
А вы не думаете?
Хотя да, "фигак-фигак-и-в-продакшен" mind-set и все дела
·>Без рефакторингов это будет дорогой ошибкой, если придётся потом что-то поменять.
Или не будет.
·>Может быть это важно для написания каких-то общеиспользуемых библиотек, но в обычных аппликухах это не так.
Мне не доводилось видеть разработки на C++ "обычных аппликух" уже лет 20, наверное.