Меня интересует идея C ++ - например, const
не это конкретное выполнение (например, отбрасывание const
).
Возьмем, к примеру, C # - ему не хватает C ++ - как const, и причина для этого обычная - люди и время. Здесь, кроме того, кажется, что команда C # посмотрела на выполнение C ++ const
, маркетинговую CLR и на этом хватило (посмотрите, почему в c # и параметре const нет метода const member ; спасибо, Свик). Будь, если мы продвинемся дальше, что-нибудь еще?
Есть ли что-то более глубокое? Возьмем, к примеру, множественное наследование - его обычно трудно понять (для пользователя), и поэтому оно не добавляется в язык (как проблема с алмазом).
Есть ли что - то в ПРИРОДЕ из const
этой позы проблемы , что лучше для языка , чтобы избежать этого? Что-то вроде принятия решения, const
должен ли он быть глубоким или неглубоким (наличие const
контейнера означает, что я не могу добавить новый элемент или изменить существующие элементы; что, если элементы относятся к ссылочному типу)?
ОБНОВЛЕНИЕ : хотя я упоминаю C # и, таким образом, делаю историческую перспективу, меня интересует характер потенциальных проблем const
языка.
Это не проблема языков. Пожалуйста, игнорируйте такие факторы, как текущие тенденции или популярность - меня интересуют только технические вопросы - спасибо.
источник
Ответы:
Обратите внимание, если это подходит для вас, но в функциональных языках, таких как Standard ML, все по умолчанию неизменяемо. Мутация поддерживается через универсальный
ref
тип erence. Таким образом,int
переменная является неизменной, аref int
переменная является изменяемым контейнером дляint
s. По сути, переменные - это реальные переменные в математическом смысле (неизвестное, но фиксированное значение), аref
s - это «переменные» в смысле императивного программирования - ячейка памяти, в которую можно записывать и читать. (Мне нравится называть их назначаемыми .)Я думаю, что проблема с
const
двоякой. Во-первых, в C ++ отсутствует сборщик мусора, который необходим для создания нетривиальных постоянных структур данных .const
должен быть глубоким, чтобы иметь какой-либо смысл, но иметь полностью неизменные значения в C ++ нецелесообразно.Во-вторых, в C ++ вам нужно выбирать,
const
а не отказываться от него. Но когда выconst
что-то забудете, а потом исправите, вы окажетесь в ситуации «отравления константой», упомянутой в ответе @ RobY, гдеconst
изменение будет касаться всего кода. Если бы этоconst
было по умолчанию, вы бы не подали заявкуconst
задним числом. Кроме того, необходимость добавлятьconst
везде добавляет много шума в код.Я подозреваю, что основные языки, которые последовали (например, Java), были в значительной степени сформированы успехом и мышлением C и C ++. Например, даже при сборке мусора большинство API-интерфейсов по сбору языков предполагают изменяемые структуры данных. Тот факт, что все является изменчивым и неизменным, рассматривается как крайний случай, что многое говорит о императивном мышлении, стоящем за популярными языками.
РЕДАКТИРОВАТЬ : После размышления на комментарии Greenoldman я понял, что
const
это не напрямую об неизменности данных;const
кодирует в тип метода, имеет ли он побочные эффекты на экземпляре.Возможно использование мутации для достижения ссылочно прозрачного поведения. Предположим, у вас есть функция, которая при последовательном вызове возвращает разные значения - например, функция, которая читает один символ
stdin
. Мы могли бы использовать кеш / запоминать результаты этой функции для создания ссылочно прозрачного потока значений. Поток будет связанным списком, чьи узлы будут вызывать функцию при первой попытке получить их значение, но затем кэшировать результат. Так что, еслиstdin
constainsHello, world!
, первый раз , когда вы пытаетесь получить значение первого узла, он будет прочитать одноchar
и возвращениеH
. После этого он продолжит возвращатьсяH
без дальнейших звонков, чтобы прочитатьchar
. Аналогично, второй узел будет читатьchar
изstdin
в первый раз вы пытаетесь получить его значение, на этот раз возвращаетеe
и кешируете этот результат.Интересно то, что вы превратили процесс, который по своей сути является состоянием, в объект, который кажется не имеющим состояния. Однако, чтобы достичь этого, необходимо было изменить внутреннее состояние объекта (путем кэширования результатов) - мутация была благоприятным эффектом . Невозможно сделать наш,
CharStream
const
даже если поток ведет себя как неизменное значение. Теперь представьте, что естьStream
интерфейс сconst
методами, и все ваши функции ожидаютconst Streams
. ВыCharStream
не можете реализовать интерфейс!( РЕДАКТИРОВАТЬ 2: Очевидно, есть ключевое слово C ++
mutable
, которое позволит нам обманывать и делатьCharStream
const
. Однако, эта лазейка разрушаетconst
гарантии - теперь вы действительно не можете быть уверены, что что-то не будет мутировать через егоconst
методы. Я полагаю, что это не так плохо, так как вы должны явно просить лазейку, но вы все еще полностью полагаетесь на систему чести.)Во-вторых, предположим, что у вас есть функции высокого порядка, то есть вы можете передавать функции в качестве аргументов другим функциям.
const
Ness является частью сигнатуры функции, поэтому вы не сможете передавать не-const
функции в качестве аргументов функциям, ожидающимconst
функции. Слепое соблюдениеconst
здесь приведет к потере общности.Наконец, манипулирование
const
объектом не гарантирует, что он не мутирует какое-то внешнее (статическое или глобальное) состояние за вашей спиной, поэтомуconst
гарантии не так сильны, как они изначально кажутся.Мне не ясно, что кодирование наличия или отсутствия побочных эффектов в системе типов - это всегда хорошая вещь.
источник
var
по требованию оставит только одну проблему - глубина?const
ссылка наconst
необъект. Несмотря на это, я не думаю, что имеет смысл иметь мелководьеconst
. Весь смысл вconst
том, что вы не сможете изменить объект с помощью этой ссылки. Вы не можете обойтисьconst
, создав неconst
ссылку, так почему было бы нормально обойтиconst
путем изменения членов объекта?func foo(const String &s)
и это сигналs
не будет изменен вfoo
.null
наследование).Основная проблема заключается в том, что программисты, как правило, не используют его достаточно, поэтому, когда они попадают в место, где это требуется, или сопровождающий позже хочет исправить правильность const, возникает огромный волновой эффект. Вы по-прежнему можете писать безупречно хороший неизменяемый код без него
const
, ваш компилятор просто не будет его применять, и его будет сложнее оптимизировать. Некоторые люди предпочитают, чтобы их компилятор не помог им. Я не понимаю этих людей, но их много.В функциональных языках почти все есть
const
, и изменчивость является редким исключением, если это вообще разрешено. Это имеет несколько преимуществ, таких как упрощение параллелизма и упрощение рассуждений об общем состоянии, но требует некоторого привыкания, если вы переходите с языка с изменчивой культурой. Другими словами, нежеланиеconst
- это проблема людей, а не техническая проблема.источник
Я вижу недостатки как:
«Отравление const» является проблемой, когда одно объявление const может заставить предыдущее или следующее объявление использовать const, и это может заставить его предыдущее из следующих объявлений использовать const и т. д. И если отравление const втекает в класс в библиотеке что у вас нет контроля, тогда вы можете застрять в плохом месте.
это не абсолютная гарантия. В большинстве случаев const защищает только ссылку, но не может защитить базовые значения по той или иной причине. Даже в C есть крайние случаи, в которые const не может попасть, что ослабляет обещание, которое предоставляет const.
в целом, настроение отрасли, похоже, отходит от сильных гарантий во время компиляции, как бы много комфорта они ни принесли вам и мне. Так что в течение дня я трачу 66% своей кодовой базы из-за отравления констант, некоторого Python Парень выполнил 10 отлично работоспособных, хорошо спроектированных, хорошо протестированных, полностью функциональных модулей Python. И он даже не взломал, когда сделал это.
Так что, возможно, вопрос в том, зачем продвигать потенциально противоречивую особенность, о которой даже некоторые эксперты неоднозначно относятся, когда вы пытаетесь освоить свой изящный новый язык?
РЕДАКТИРОВАТЬ: краткий ответ, новый язык имеет крутой холм, чтобы подняться для принятия. Это дизайнеры действительно должны задуматься о том, какие функции он должен получить принятие. Возьми Go, например. Google как бы жестоко обрезал некоторые из самых глубоких религиозных баталий, делая несколько вариантов дизайна в стиле Конана-варвара, и я на самом деле думаю, что язык лучше для него, из того, что я видел.
источник
int *
изменяемый указатель на изменяемое значение,int const *
изменяемый указатель на постоянное значение, постоянныйint * const
указатель на изменяемое значение, постоянныйint const * const
указатель на постоянное значение.const
), поэтому такие «причины» я считаю неактуальными (по крайней мере, для этого вопроса). Проconst
отравление - можете привести пример? Потому что AFAIK это преимущество, вы что-то пропускаетеconst
и оно должно остатьсяconst
.const
проблема, но изменение типа действительно - что бы вы ни делали, это всегда будет проблемой. Подумайте о прохожденииRichString
, а потом понимаете, что вам лучше пройтиString
.const
. Это слишком легко, чтобы не делатьconst
вещи, которые должны быть,const
потому что вы должны согласиться на это, а не на это.Есть некоторые философские проблемы в добавлении
const
к языку. Если вы объявляетеconst
классу, это означает, что класс не может измениться. Но класс - это набор переменных, связанных с методами (или мутаторами). Мы достигаем абстракции, скрывая состояние класса за набором методов. Если класс предназначен для сокрытия состояния, тогда вам нужны мутаторы, чтобы изменить это состояние извне, и тогда его ужеconst
нет. Таким образом, можно объявитьconst
только неизменяемые классы. Так чтоconst
кажется возможным только в сценариях, где классы (или типы, которые вы хотите объявитьconst
) тривиальны ...Так что нам нужно в
const
любом случае? Я так не думаю. Я думаю, что вы можете легко обойтись безconst
хорошего дизайна. Какие данные вам нужны и где, какие методы являются методами данных к данным и какие абстракции вам нужны для ввода-вывода, сети, представления и т. Д. Затем вы естественным образом разделяете модули и классы, которые имеют дело с состоянием, и у вас есть методы и неизменные классы, которые не нуждаются в состоянии.Я думаю, что большинство проблем возникает с большими толстыми объектами данных, которые могут сохранять, преобразовывать и рисовать себя, а затем вы хотите передать их рендереру, например. Таким образом, вы не можете скопировать содержимое данных, потому что это слишком дорого для большого объекта данных. Но вы тоже не хотите, чтобы это изменилось, поэтому вам нужно что-то, как
const
вы думаете. Позвольте компилятору выяснить ваши недостатки дизайна. Однако если вы разделяете эти объекты только на неизменяемый объект данных и внедряете методы в ответственном модуле, вы можете обойти (только) указатель и делать то, что вы хотите делать с данными, при этом гарантируя неизменность.Я знаю, что в C ++ можно объявлять некоторые методы
const
и не объявлять другие, потому что они являются мутаторами. И потом, через некоторое время вам нужен кеш, а затем получатель мутирует объект (потому что он загружается лениво), и этоconst
больше не так . Но в этом весь смысл этой абстракции, верно? Вы не знаете, какое состояние мутирует с каждым звонком.источник
const
(в смысле C ++ ) вы должны определить интерфейс, также для всех свойств.