Здравствуйте, GlebZ, Вы писали:
GZ>Не-а. Тут как раз и есть плюсы такого подхода. Для того чтобы получить другую сеть не обязательно клонировать объекты. Один и тот же объект неизменяем и может лежать в любой подсети. Меняется ведь только ссылка на него.
А с чего ты взял, что ссылка на объект только одна?
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, kan, Вы писали:
kan>>А в каком языке есть const, но нет const_cast? GZ>Есть понятие mutable/unmutable. Оно в функциональных языках часто присутсвует. Причем unmutable(неизменяемый) — это основной стиль.
Только immutable а не unmutable.
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, _FRED_, Вы писали:
_FR>>Здравствуйте, GlebZ, Вы писали:
kan>>>>А в каком языке есть const, но нет const_cast? GZ>>>Есть понятие mutable/unmutable. Оно в функциональных языках часто присутсвует. Причем unmutable(неизменяемый) — это основной стиль.
_FR>>Константность объекта и константность ссылки на него — разные вещи. Я подозреваю, что "в функциональных языках" под "unmutable(неизменяемый)" понимают неизменяемость ссылки, а вовсе не данных, на которые она указывает. GZ>
GZ>immutable i=10;
GZ>mutable i=10;
GZ>
Во-первых ключевого слова immutable в Nemerle нет (все по умолчанию immutable), пишут просто
def i = 10;
или если член класса то вообще просто
i : int;
.
А во-вторых FR говорил вот про что:
[Record]
class A
{
public mutable x : int;
public static Main() : void
{
def a1 = A(1);
//a1 = A(2); // ошибка компиляции - a1 неизменяемая!
a1.x = 5; // a объект на который она указывает - изменяемый!
System.Console.WriteLine($"a1.x = $(a1.x)"); // выдает "a1.x = 5"
}
}
В С++ можно действовать более гибко, хотя больше писанины:
class A
{
public:
int x;
A(int _x) : x(_x) {}
};
int main()
{
const A* a1 = new A(1); // указатель на неизменяемый объект
//a1->x = 5; // ошибка компиляции - неизменяемый объект изменять нельзя!delete a1;
a1 = new A(2); // а сам указатель - можно!delete a1;
/////////////////////////////////////////////////
A *const a2 = new A(1); // константный указатель на изменяемый объект
a2->x = 5; // объект изменять можно
//a2 = new A(2); // ошибка компиляции - указатель изменять нельзя!delete a2;
/////////////////////////////////////////////////const A *const a3 = new A(1); // константный указатель на неизменяемый объект
//a3->x = 5; // ошибка компиляции - константный объект изменять нельзя!
//a3 = new A(2); // ошибка компиляции - указатель тоже изменять нельзя!delete a3;
return 0;
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: Нет возможности использовать константные ссылки
Здравствуйте, AndreiF, Вы писали:
GZ>>Не-а. Тут как раз и есть плюсы такого подхода. Для того чтобы получить другую сеть не обязательно клонировать объекты. Один и тот же объект неизменяем и может лежать в любой подсети. Меняется ведь только ссылка на него.
AF>А с чего ты взял, что ссылка на объект только одна?
Не понял? Ссылок может быть много. Экземпляр объекта один.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[6]: Нет возможности использовать константные ссылки
GlebZ wrote: > C>А теперь представь, что у тебя сеть объектов. Каждый раз будешь всю сеть > C>клонировать? > Не-а. Тут как раз и есть плюсы такого подхода. Для того чтобы получить > другую сеть не обязательно клонировать объекты. Один и тот же объект > неизменяем и может лежать в любой подсети. Меняется ведь только ссылка > на него.
Вот тебе ситуация, объекты А и Б циклически связаны друг с другом:
struct A
{
B *b;
};
struct B
{
A *a;
};
Если я создаю новый A, оставив у него ссылку на старый объект, то
получится интересная ситуация:
A *oldA;
A *newA=doSomething(oldA);
assert(newA->b->a == newA); //WTF?????
Чтобы ее разрулить нужно будет клонировать еще и объект B. Ну и все
связаные с ним объекты.
Почему я об этом говорю — у меня была именно такая ситуация, которую я
разрулил введением контекстных ссылок. То есть значение ссылки у меня
зависит от контекста. Получается достаточно большой overhead, но у меня
контексты являются достаточно грубыми единицами деления (с помощью них
организуются транзакции на графе объектов), так что в моем случае это не
так страшно. А вот если контекст создавать на каждое изменение
переменной....
Здравствуйте, kan, Вы писали:
kan>WolfHound wrote:
>>> > Вот за const_cast нужно бить морду. Причем сильно, длого и прилюдно. >> kan>А в каком языке есть const, но нет const_cast? >> Ты лучше покажи язык кроме С++ где этот самый const_cast есть... kan>Потому что это единственный (мне известный) язык (не функциональный) где есть const. kan>Автор вопроса о const явно подразумевал C#, на крайняк CLI, что явно не функциональные языки.
Т.е. кроме C++ ты больше языков и не знаешь? Кроме функциональных...
AF>Нет ни множественного наследования реализаций, ни его заменителей.
+1, непомешала бы автоматизация реализации интерфейса через агрегацию, как это умеет Delphi. Но вообще это не так уж часто нужно.
AF>Нельзя перегружать методы по типу возвращаемого значения.
И как компилятор будет различать, какой метод вызывать, если ты забиваешь на возвращаемое значение или засовываешь его в object ИМХО, нафиг не надо. Ну вот ни разу не сталкивался с такой проблемой.
AF>Нет кортежей.
C# 3.0?
AF>Критически важные системные исключения (OutOfMemoryException, ThreadAbortException, ExecutionEngineException и т.п.) наследуются от того же базового класса, что и частно используемые ArgumentException, NotSupportedException и так далее. Это провоцирует плохих программистов писать конструкции наподобие AF>catch (Exception) { return false; }
По-моему такое ничто никого не провоцирует писать. Не видел. Не понимаю.
Хотя критические исключения, конечно, стоило бы отделить.
AF>Наличие типов, которые явно обозначаются как передаваемые через стек, и все связанные с этим усложнения системы типов (боксинг) и ограничения (нельзя наследовать от структур). На самом деле, решать, каким образом передавать объект в каждом конкретном случае – это задача оптимизатора.
Не согласен. Более того, там все не так просто, если подумать. Как только ты допускаешь наследование — ты принципиально теряешь возможность размещения объекта в стеке/в теле другого объекта, т.к. размер перестает быть фиксирован.
AF>Просчеты в реализации энумов. Например, любое числовое значение можно привести к любому перечислимому типу, даже если в том нет соответствующего значения, и это не вызовет никакой ошибки во время выполнения. Фактически, целевой переменной перечислимого типа будет присвоено некоторое «неопределенное» значение. No comments.
Это ерунда. Пишешь свой класс с перечислением по аналогии и все. Можно туда еще методов любых напихать, будет как в JDK 1.5
AF>Коллекции AF>Одновременное применение в системе типов .NET массивов, нетипизированных коллекций, специализированных коллекций и генерик-коллекций, которые все «немного похожи» и «немного разные». Соответственно, методы из FCL возвращают разные типы — это создает лишнюю путаницу и сложности при программировании.
Это обратная совместимость Куда деваться?
AF>Для массивов возможна ко/контра-вариантность элементов, для остальных коллекций – нет. Массивы можно инициализировать списком значений в коде, для коллекций это невозможно.
AF>Большинство коллекций поддерживают возможность добавлять элементы без пересоздания объекта, для массивов эта возможность недоступна. Для большинства коллекций доступен метод AsReadOnly() или аналог, для массивов такой возможности нет.
Это нормально.
AF>Генерики AF>Много лишней писанины, если нужно создать систему из нескольких связанных типов, имеющих общие параметры.
Можно подробнее?
AF>Нельзя использовать Enum в качестве констрэйнта на тип.
Еще странные ограничения generics: CBO, Attribute, Delegate.
И очень не хватает авто-интерфейсов-враперов, чтобы можно было использовать в качестве параметров generic'ов типы, которые создавались без оглядки на generics.
Здравствуйте, WolfHound, Вы писали:
VD>>Ради справедливости надо заметить, что тогда по уму нужно отказываться вообще от вэлью-типов. Это снимет море проблем. WH>Каких проблем?
Коваринтность будет доступна почти везде. Можно будет отказаться от боксинга. Упростится модель абстракйий. В общем, много чего упростится. А компилятор может скомпенсировать потери в производительности.
В общем, я считаю, что когда-то, когда уровень рантаймов и компиляторов выростет до невероятных высот такой дизайн будет самым верным (собственно дизайн Смолтока, от части). Но на время выпуска первого фрэймворка выбор МС был конечно оправдан.
VD>>Но оптимизатр при этом должен будет быть просто зверским. Иначе будет ну очень не быстро и расточительно по памяти. WH>И должен он будет работать в глобальном масштабе...
Джит уже работает в глобальном масштабе, если таковым считать масштаб процесса.
WH>Ибо если на тойже виртуальной машине сделать межпроцессное общение типа как в сингулярити...
И что будет? Все будет ОК. Там взаимодействие ведется неизменяемыми типами.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vdimas, Вы писали:
V>И потеряем одно интересное св-во. Для вэлью типа логически верно то экземпляр и его копия — это одно и то же. Удобное весьма св-во. Для классического ОО два экземпляра объекта — это как бы означает два разных объекта.
Не потеряем. Семантика вэлю-типов отлично эмулируется.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, kan, Вы писали:
kan>А в каком языке есть const, но нет const_cast?
Вольфхаунд прав. const_cast — это бред придуманный только в С++.
В других языках обычно и const нет. Вместо этого там просто есть неизменяемые переменные. Более того есть зыки в которых все переменные не изменяемые (Хаскель, например).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndreiF, Вы писали:
AF>Пардон, и правда ошибся. Просто в первой версии этого не было. AF>Странно только, зачем они сделали этот метод у массивов статическим.
Потому-что массив на самом деле не объект, а встроенный тип данных. Но в конкретном ЯП можно было бы это и скрыть. В C# 1-2 не скрыли. В трешке будут методы расширения и на них можно будет все поправить.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2 wrote: > kan>А в каком языке есть const, но нет const_cast? > Вольфхаунд прав. const_cast — это бред придуманный только в С++. > В других языках обычно и const нет. Вместо этого там просто есть > неизменяемые переменные. Более того есть зыки в которых все переменные > не изменяемые (Хаскель, например).
Так неизменяемые переменные не нужны, а нужен контекст, в котором
нельзя изменять объекты.
На самом деле, const — это один простейших типов программирования по
контракту. Модификатором 'const' мы обозначаем, что метод не меняе
инвариант класса.
Как раз стоило бы развить эту идею для большего статического контроля
правильности программы. Или ты против статического контроля?
Здравствуйте, Cyberax, Вы писали:
C>Так неизменяемые переменные не нужны, а нужен контекст, в котором C>нельзя изменять объекты.
Это ты сказал не подумав.
C>На самом деле, const — это один простейших типов программирования по C>контракту. Модификатором 'const' мы обозначаем, что метод не меняе C>инвариант класса.
const в С++ используется для разных целей. Собственно это и приводит к путаннице.
Не спорю идея пометки тел методов как неизменяемых — хорошая идея. Но идеи неизменяемых переменных это не отменяет.
C>Как раз стоило бы развить эту идею для большего статического контроля C>правильности программы. Или ты против статического контроля?
Не против. Но хотелось бы, чтобы пометка метода как неизменяющего состояние класса гарантировало бы это на сто процентов. А вот в С++ такой гарантии нет.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Нет возможности использовать константные ссылки
Здравствуйте, GlebZ, Вы писали:
GZ>Не понял? Ссылок может быть много. Экземпляр объекта один.
Всё очень просто. Если у тебя есть объекты, которые образуют граф, то ты не можешь скопировать один из объектов в отдельности. В частном случае это бывает возможно, но в общем случае — нет.
Здравствуйте, Igor Trofimov, Вы писали:
AF>>Генерики AF>>Много лишней писанины, если нужно создать систему из нескольких связанных типов, имеющих общие параметры.
iT>Можно подробнее?
Очень упрощенный пример (на самом деле там должна быть еще куча разных методов и пропертей)
public class EpsTransition
{
public State Target;
}
public class Transition
{
public char Token;
public State Target;
}
public class State
{
public List<EpsTransition> EpsTransitions = new List<EpsTransition>();
public List<Transition> Transitions = new List<Transition>();
}
public class StateMachine
{
public State EntryPoint;
public List<State> States = new List<State>();
}
А теперь пробуем сделать очень простую вещь — заменить тип Transition.Token, вместо char сделать параметризованный тип.
Здравствуйте, VladD2, Вы писали:
VD>Не против. Но хотелось бы, чтобы пометка метода как неизменяющего состояние класса гарантировало бы это на сто процентов. А вот в С++ такой гарантии нет.
VladD2 wrote: > C>Так неизменяемые переменные не нужны, а нужен *контекст*, в котором > C>нельзя изменять объекты. > Это ты сказал не подумав.
Я имею в виду, что не нужны для тех целей, для которых используется const.
> Не спорю идея пометки тел методов как неизменяемых — хорошая идея. Но > идеи неизменяемых переменных это не отменяет.
Естественно, иммутабельные переменные, в частности, значительно упрощают
многопоточное программирование.
> C>Как раз стоило бы развить эту идею для большего статического контроля > C>правильности программы. Или ты против статического контроля? > Не против. Но хотелось бы, чтобы пометка метода как неизменяющего > состояние класса гарантировало бы это на сто процентов. А вот в С++ > такой гарантии нет.
Есть мнение, что 100% гарантия не очень нужна. Сейчас посмотрел свой код
— на 4Мб исходников на С++ приходится 120 const_cast'ов. Примерно
половину из них можно убрать без всяких проблем (там они просто
сберегают несколько строк кода), еще часть можно было бы убрать, если
хорошо подумать. Но вот что делать с остальными — непонятно.
Так что я лучше буду жить с не-100%-ной гарантией, что объект не
изменится в const-методе или через const-ссылку.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[9]: Нет возможности использовать константные ссылки
Здравствуйте, kan, Вы писали:
kan>Так разговор идёт о const — позволяет делать что-то типа мутабельности (но не совсем её) на уровне методов, притом kan>проверка compile-time (!), а не "as documented". Как в C# узнать, что данный объект немутабельный? Правильно — залезть в kan>документацию (если она есть, иначе — сорцы, если они есть, иначе — вешаться) и прочитать. Больше никак. Как узнать, что kan>данный метод можно вызвать без клонирования объекта, дабы чьи-нибудь данные не попортить? Правильно — залезть в kan>сорцы/документацию. Больше никак. kan>А если вдруг какой-нибудь метод изменили и он стал изменять состояние? Старый код об этом никак не узнает.
Это не свойство ссылки как в С++. Это свойство типа. Мы же не возмущаемся что unsigned int кто-то может перебить как signed int,
>> случае очень показательны константные строки в C++. Там есть режим kan>Не понял что этот пример показывает... просто оптимизация, сташвая возможной, благодая нестрогости стандарта.
Нет. Это эквивалентность.
>> нарушить данное правило. kan>Нет, идея С++ в том, что он небезопасный — можно нарушить любое правило.
Это не идея C++. Это проблема С++. Нельзя ни в чем быть увереным, и чаще короткий путь — путь нарушения контракта.
kan>Как именно поддерживает? Чем эта поддержка принципиально отличается от C++? Можно ссылку.
MSDN.
kan>Мягко говоря, не очень... скорее тут "виноваты" шаблоны, stl не при чём, а это исчисление типов, метапрограммирование.
Советую проникнуться что такое функциональное программирование и что эмулирует функтор.
АХ>Во-первых ключевого слова immutable в Nemerle нет (все по умолчанию immutable), пишут просто
Пришлось жертвовать ради наглядности.
АХ>А во-вторых FR говорил вот про что: АХ>
АХ>[Record]
АХ>class A
АХ>{
АХ> public mutable x : int;
АХ> public static Main() : void
АХ> {
АХ> def a1 = A(1);
АХ> //a1 = A(2); // ошибка компиляции - a1 неизменяемая!
АХ> a1.x = 5; // a объект на который она указывает - изменяемый!
АХ> System.Console.WriteLine($"a1.x = $(a1.x)"); // выдает "a1.x = 5"
АХ> }
АХ>}
АХ>
Нехороший стиль.
АХ>В С++ можно действовать более гибко, хотя больше писанины:
А теперь оказывается что нельзя быть увереным что объект не изменяется. Нарушать это правило может как другой код, написанный другим программистом. А в случае многопоточки вообще нехорошо получается. В immutable типе размывается понятие value — reference типа при передаче в функцию. В случае если у компилятора доступна информация о том, что объект не будет изменяться он его может передавать как по ссылке, так и по значению. И вообще более часто задействовать редукцию/инлайнинг.
Здравствуйте, AndreiF, Вы писали:
AF>В С++ вообще нет никаких гарантий
Скажу больше. Гарантии вообще редко можно встретиь. И даже если встретишь, то по жизни оказвается, что и это обман.
Вот давича купил я себе память для нового компьютера. На ней написано "пожизненная гарантия". Ну, и что вы думаете? В гарантийном талоне написано — один год.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.