Re[31]: i++; ++i; ;) (-)
От: Erop Россия  
Дата: 04.06.09 08:22
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Чтобы было прмерно так: int i; i someOp param; и число i после этого изменилось.

i++;
Но это всё не о том спор. Есть некие "значения" строк, они неизменны, так как являются абстракцией существующей исключительно в нашей голове. Ну там скажем строка "мама" или число "0,5"...
А есть переменные, которые могут принимать то или иное значение. Значения, конечно, менять нельзя, но содержащие их переменные иногда можно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[30]: Ну ты вообще многого не видишь... ;)
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.06.09 08:29
Оценка: +1
Здравствуйте, alexey_ma, Вы писали:
_>Вон оказывается оно как Только причем здесь окружающая среда? Замечательно если вы сами можете определять контракты и аспекты представления, ну а если Вам нужно взаимодествовать с какой-то legacy аппликацией написанной 20 лет назад и использующей свой собственный извращенный стринг, что делать то?
Читать инструкцию про platform invoke. Вопросы конвертации представления строк там решены. Благодаря тому, что они отделены от контракта собственно строки, конвертеры стоят не так дорого, как типичный "класс строка" из произвольной плюсовой библиотеки.

_>Впрочем спорить не буду, возможно в 95% процентах случаев дотнетовский стринг вполне удобен, используйте и радуйтесь. Меня же радует в С++ многообразие стрингов из разных библиотек и возможность выбора наиболее подходящего и эффективного для каждого конкретного случая.

Не путайте возможность и необходимость. Именно такое похабное отношение к строкам с самого начала и привело к тому, что в С++ появилось "многообразие стрингов из разных библиотек" и необходимость трахаться с их интероперабельностью.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[31]: Ну ты вообще многого не видишь... ;)
От: alexey_ma Израиль  
Дата: 04.06.09 08:32
Оценка:
Здравствуйте, Mamut, Вы писали:

a>> Вон оказывается оно как Только причем здесь окружающая среда? Замечательно если вы сами можете определять контракты и аспекты представления, ну а если Вам нужно взаимодествовать с какой-то legacy аппликацией написанной 20 лет назад и использующей свой собственный извращенный стринг, что делать то? Впрочем спорить не буду, возможно в 95% процентах случаев дотнетовский стринг вполне удобен, используйте и радуйтесь. Меня же радует в С++ многообразие стрингов из разных библиотек и возможность выбора наиболее подходящего и эффективного для каждого конкретного случая.


M>Угу, потом пытаешься скрестить QString с bt_str и материшься трехэтажным матом

Угу. Бывает конечно и такое. Если самому можно определять какую библиотеку использовать то вопросы межвидового взаимодействия как правило не стоят, или решаются административным порядком. Но дело в том что я довольно много занимаюсь вопросами интеграции и взаимодействия с сторонними аппликациями ( иногда весьма старыми и экзотическими) и здесь "окружающая среда" имеет решающее значение. Я далеко не всегда могу выбирать то что мне нравиться ( в том числе иногда и сам язык),часто приходиться мириться с тем что есть. . В этом плане С++ с его многообразием библиотек более универсален чем С#.
Re[20]: Ну ты вообще многого не видишь... ;)
От: alexey_ma Израиль  
Дата: 04.06.09 08:35
Оценка: +1 :)
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, WolfHound, Вы писали:


И>>>А в С# для этого пришлось городить огород в виде двух классов: String и StringBuilder.

WH>>Этот огород исключительно из-за того что мелкософты не осилили эффективную реализацию строк.

PD>А до них Sun в Java тоже не освоила, так ? Не осваивается оно...

Точно. Универсальное редко бывает максимально эффективным. Возможно что лучше иметь несколько алтернативных реализаций.
Re[23]: Ну ты вообще многого не видишь... ;)
От: Pavel Dvorkin Россия  
Дата: 04.06.09 08:46
Оценка: +1 :)
Здравствуйте, Sinclair, Вы писали:

Можно я свои 3 копейки добавлю ?

S>Да-да, вы как раз вносите путаницу. Конечно же, алгоритм, заложившийся на константность объекта, никак не сможет работать с неконстантым. Например, из константности мы можем вывести возможность не делать блокировок при обращении; можем полагаться на то, что хеш будет неизменным; много на что еще можем полагаться. Неконстантность ничего этого не даёт, поэтому алгоритмы на С++ невозможно оптимизировать подобным образом.


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

Что такое иммутабельность, в конце концов ? Грубо говоря, это порождение констант в рантайме. С++ этого не умеет. Java и C# умеют, но только для типа string. Как только мы попробуем развить идею иммутабельности для любых классов, так мы сразу придем к задаче, примерно эквивалентной работе GC — проверке на каждой операции, не достижим ли данный объект из какого-нибудь иммутабельного объекта. string слишком прост, поэтому для него такое возможно, в нем нет вложенных объектов.

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

С другой стороны, необходимо ответить на вопрос — насколько часто придется все же менять эти иммутабельные объекты. Я не оговорился, слово "менять" я понимаю здесь в широком смысле, то есть создавать их измененные версии, независимо от того, как именно. Если объекты не являются иммутабельными, то во многих случаях эти изменения можно делать inplace (примеры — преобразование к иному регистру, замена символа на другой, реверс). Если объект является иммутабельным, то эти действия приходится выполнять с помощью создания нового объекта, нового string в конечном счете, опять же иммутабельного.

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

Так что истина конкретна. Иногда это хорошо, иногда нет. Но то, что в Java/C# это есть, а в C++ — нет — в общем-то, плюс этим двум языкам.
With best regards
Pavel Dvorkin
Re[26]: Ну ты вообще многого не видишь... ;)
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.06.09 08:46
Оценка: :)
Здравствуйте, CreatorCray, Вы писали:

CC>Так отдавай туда const char * — и ежу понятно что менять сие без хака низя.

Опять упорствующее непонимание. Отдать-то я могу. А как мне при приёме обеспечить константность?
CC>А если авторы кода, куда ты передаешь строку, внутрях снимают константность, то тебе в этом случае вообще никакие иммутабельные строки не помогут. Если уж тут сняли константность то в случае иммутабельной строки — полезут напрямую в память и поменяют буфер "иммутабельной" строки.
Всё наоборот. Вот у меня код
void ProcessInAnotherThread(const char* achtung);


Этот код пишу я. Вызывают его другие. Вот этот const означает, что я не имею права его менять. Но вызывающая сторона имеет полную свободу — я не могу, оставаясь в рамках С++, обеспечить неизменность этой строки.
CC>Это С++!!! (СПАРТААААА!!!!)
Это отстой, а не спарта.
CC>Это не C# — тут суровые бородатые викинги с топорами.

CC>Если есть в руках индуса указатели — тебя ничего не спасёт.

Не надо вот этих вот "ля-ля". В руках индуса... Ничто не спасёт... Этими мантрами люди, покусанные плюсами, убеждают себя уже двадцать лет. А тем временем другие люди, с более взвешенным отношением к индустрии, демонстрируют, что можно значительно увеличивать надёжность программ безо всяких мантр и подготовок личного состава.
Да, я в курсе, что при особом желании высокодоверенный код в С# может сломать иммутабельность строк. Но это — малоизвестная и труднодостижимая техника. А в вашей убогой спарте запросто можно отчудить вот такое:
std:string hello("hello");
void ProcessInAnotherThread(hello.c_str());
hello.clear(); // oops!

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

CC>В шарпе отобрали возможность делать что угодно с любой областью памяти — поэтому там можно надеяться на "гарантии иммутабельности". Впрочем все равно можно дёрнуть native код и поковыряться указателем в памяти. И тогда все надежды гарантии пойдут лесом, как и в С++ случае.

CC>Поэтому не надо тащить методы работы с C# в С++ где всё совсем по другому.
Я в курсе, как там что в С++. Я, вообще-то, не с С# работать начал.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[32]: Ну ты вообще многого не видишь... ;)
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.06.09 08:46
Оценка: :))
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Хм. А в MSDN я вот такое увидел


PD>fixed (char* p = str) ... // equivalent to p = &str[0]

Угу. Это ансейф, и он по умолчанию запрещен.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[30]: Ну ты вообще многого не видишь... ;)
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.06.09 08:46
Оценка: -1
Здравствуйте, CreatorCray, Вы писали:

CC>А можно как нибудь подтвердить реальными фактами это утверждение?

CC>Или "мало-мальски полезные иммутабельные строки" это 1:1 как в шарпе и никак иначе?
Не обязательно 1:1. Достаточно иметь просто иммутабельные строки, которые не требуют O(N) при интеропе с окружающим кодом.
Увы, сие в плюсах решительно невозможно. Единственный способ для библиотеки потребовать от внешнего кода передачи иммутабл строки — это выполнить копию в момент передачи.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[33]: Ну ты вообще многого не видишь... ;)
От: Pavel Dvorkin Россия  
Дата: 04.06.09 08:53
Оценка: +1 :)
Здравствуйте, Sinclair, Вы писали:

S>Угу. Это ансейф, и он по умолчанию запрещен.


Перефразируя не помню уж кого, скажу, что между "запрещен" и "по умолчанию запрещен" разница такая же, как между государем и милостивым государем
With best regards
Pavel Dvorkin
Re[31]: Ну ты вообще многого не видишь... ;)
От: alexey_ma Израиль  
Дата: 04.06.09 08:54
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, alexey_ma, Вы писали:


S>Не путайте возможность и необходимость. Именно такое похабное отношение к строкам с самого начала и привело к тому, что в С++ появилось "многообразие стрингов из разных библиотек" и необходимость трахаться с их интероперабельностью.

Еще раз, в ваших собственных проектах можете не трахаться, административно, на основании тех или иных требований заказчика определяте какую библиотеку использовать и все вопросы по интероперабельность отпадают. Но как вы справедливо заметили есть еще и окружающая среда, которая часто не знакома с майкрософтом и дотнетом.
У меня же нет выбора и я по роду своей работы вынужден с ней трахаться. Поверьте, дотнет в таких случая не помошник, попробуйте написать на шарпе програмку получающую текст с экрана терминального эмулятора написанного неизвестными испанскими коллегами лет десять назад и не имеющим не только внешнего АРI и но и вообше какойлибо документациию. Я конечно могу порекомендовать клиенту поменять этот терминал на другой имеющий hllapi или комовский интерфейс который я смогу задействовать из C#. Но вы наверное догадиваетесь куда я буды послан вместе с своими требованиями, клиенту нет никакого резона менять то что учтойчиво и надежно работало за много лет до появления дотнета.
Re[32]: i++; ++i; ;) (-)
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 04.06.09 09:02
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, gandjustas, Вы писали:


G>>Чтобы было прмерно так: int i; i someOp param; и число i после этого изменилось.

E>
i++;
Но это всё не о том спор. Есть некие "значения" строк, они неизменны, так как являются абстракцией существующей исключительно в нашей голове. Ну там скажем строка "мама" или число "0,5"...

E>А есть переменные, которые могут принимать то или иное значение. Значения, конечно, менять нельзя, но содержащие их переменные иногда можно...
В данном случае ты говоришь об эксклюзивном ключе. Здесь есть езменяемая и неизменяемая часть.
разделение строк на 2 типа необходимо по нескольким причинам.
1. Хэш неизменен, а значит хранение в хэштаблице в том числе для интернирования для скорости сравнения по указателям и экономии памяти.

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

3. Отсутствие синхронизации при чтении строк.
и солнце б утром не вставало, когда бы не было меня
Re[24]: Ну ты вообще многого не видишь... ;)
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.06.09 09:04
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Что такое иммутабельность, в конце концов ? Грубо говоря, это порождение констант в рантайме. С++ этого не умеет. Java и C# умеют, но только для типа string. Как только мы попробуем развить идею иммутабельности для любых классов, так мы сразу придем к задаче, примерно эквивалентной работе GC — проверке на каждой операции, не достижим ли данный объект из какого-нибудь иммутабельного объекта. string слишком прост, поэтому для него такое возможно, в нем нет вложенных объектов.

Не всё так сложно, о мой давний противник
1. Если объект не имеет исходящих ссылок, то недостижимость крайне легко доказывается. См. например DateTime — он тоже полностью Immutable (что гораздо лучше, чем в Java).
2. Если объект имеет исходящие ссылки, то при проектировании его достаточно убедиться, что сами они показывают только на иммутабельные объекты.
Поэтому сделать вот такой класс immutable — проще простого:
public class Name
{
  public Name(string firstName, string lastName)
    {
      _firstName = firstName;
        _lastName = lastName;
    }
    
  public string FirstName { get { return _firstName;}}
  public string LastName { get { return _lastName;}}
    
    public Name ChangeFirstName(string newFirstName)
    {
      return new Name(newFirstName, this.LastName);
    }

    public Name ChangeLastName(string newLastName)
    {
      return new Name(this.FirstName, newLastName);
    }
}


PD>С другой стороны, необходимо ответить на вопрос — насколько часто придется все же менять эти иммутабельные объекты. Я не оговорился, слово "менять" я понимаю здесь в широком смысле, то есть создавать их измененные версии, независимо от того, как именно. Если объекты не являются иммутабельными, то во многих случаях эти изменения можно делать inplace (примеры — преобразование к иному регистру, замена символа на другой, реверс). Если объект является иммутабельным, то эти действия приходится выполнять с помощью создания нового объекта, нового string в конечном счете, опять же иммутабельного.

Совершенно верно.
PD>Отсюда ясно, что эффект от иммутабельности может быть как существенным и положительным, так и существенным и отрицательным. Если генерировать набор строк, не меняя длины исходной строки, а только заменяя в ней символы, то без иммутабельности эта задача решается на одной строке, одном буфере. С иммутабельностью мы рискуем захватить мегабайты, прежде чем проснется GC и уничтожит всю эту иммутабельную кунсткамеру. Более того, на нелюбиом тобой массиве из char (ASCIIZ то есть) эти операции можно выполнять на одном буфере даже при изменении длины строки, лишь бы только за пределы буфера не выходить.
Совершенно верно. К счастью, обычно автор программы достаточно хорошо себе представляет, какие операции он хочет делать с текстом и насколько часто. И если ему нужно часто вносить изменения в строку, он применяет StringBuilder.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[31]: Ну ты вообще многого не видишь... ;)
От: CreatorCray  
Дата: 04.06.09 09:06
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Не обязательно 1:1. Достаточно иметь просто иммутабельные строки, которые не требуют O(N) при интеропе с окружающим кодом.

S>Увы, сие в плюсах решительно невозможно.
Доказательства решительной невозможности будут?
В С++ такие строки могут быть нужны "под задачу". А в этом случае весь интероп с окружающим кодом легко свести к присвоению начального значения.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[27]: Ну ты вообще многого не видишь... ;)
От: CreatorCray  
Дата: 04.06.09 09:06
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, CreatorCray, Вы писали:


CC>>Так отдавай туда const char * — и ежу понятно что менять сие без хака низя.

S>Опять упорствующее непонимание. Отдать-то я могу. А как мне при приёме обеспечить константность?
А! Теперь понятно о чем ты.

S>Этот код пишу я. Вызывают его другие. Вот этот const означает, что я не имею права его менять. Но вызывающая сторона имеет полную свободу — я не могу, оставаясь в рамках С++, обеспечить неизменность этой строки.

Дык этож C# подход, для С++ надо делать иначе.

S>Не надо вот этих вот "ля-ля". В руках индуса... Ничто не спасёт... Этими мантрами люди, покусанные плюсами, убеждают себя уже двадцать лет. А тем временем другие люди, с более взвешенным отношением к индустрии, демонстрируют, что можно значительно увеличивать надёжность программ безо всяких мантр и подготовок личного состава.



S> А в вашей убогой спарте запросто можно отчудить вот такое:

S>
S>std:string hello("hello");
S>ProcessInAnotherThread(hello.c_str());
S>hello.clear(); // oops!
S>

S>И никаких средств защититься от этого не предусмотрено.
Это средство называется головной мозг.
Если в твоих терминах, то это код "покусанного C#".
Мне почему-то в голову такую дурость на С++ утворить не приходит.

CC>>Поэтому не надо тащить методы работы с C# в С++ где всё совсем по другому.

S>Я в курсе, как там что в С++. Я, вообще-то, не с С# работать начал.
Я понимаю. Но у тебя моск уже заражён шарпом, раз ты пытаешься писать на С++ как на шарпе.
Естественно получается фигня: подходы то не те.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[31]: Ну ты вообще многого не видишь... ;)
От: Юрий Жмеренецкий ICQ 380412032
Дата: 04.06.09 09:06
Оценка: +1
Здравствуйте, alexey_ma, Вы писали:
...
_>Так это для наглядности. На самом деле вместо указателя можно изпользовать address-of operator — & для конкретной переменной. Просто такой код не имееет смысла в С++, поскольку адресс переменной не бывает нулевой. Я вообще-то склонен согласиться с Игорем что кода вида
_>
_>int* n = null
_>

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

В бусте как раз есть optional<T> (и умные указатели здесь не причем), и его семантика ближе к Nullable в C#, чем к указателям в С++:

For instance, optional<> does not have shallow-copy so does not alias: two different optionals never refer to the same value unless T itself is a reference (but may have equivalent values). The difference between an optional<T> and a pointer must be kept in mind, particularly because the semantics of relational operators are different: since optional<T> is a value-wrapper, relational operators are deep: they compare optional values; but relational operators for pointers are shallow: they do not compare pointee values. As a result, you might be able to replace optional<T> by T* on some situations but not always.
...
bool operator < ( optional<T> const& x, optional<T> const& y );
Returns: If y is not initialized, false. If y is initialized and x is not initialized, true. If both x and y are initialized, (*x < *y).

...
bool operator == ( optional<T> const& x, optional<T> const& y );
Returns: If both x and y are initialized, (*x == *y). If only x or y is initialized, false. If both are uninitialized, true.

Re[25]: Ну ты вообще многого не видишь... ;)
От: Игoрь Украина  
Дата: 04.06.09 09:10
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Игoрь, Вы писали:


И>>Не, ну хорошо, кто бы спорил. Раз подходит для каких-то задач, замечательно. Мне такое пока не нужно.

WH>Нужно просто ты сам пока этого не понимаешь.
WH>Дело в том что тут работает парадокс блаба
Автор(ы): Чистяков Влад (VladD2)
Дата: 03.03.2007
Язык программирования Nemerle заинтересовал многих в первую очередь своей мощнейшей подсистемой мак-росов. Однако и без них Nemerle предоставляет ряд су-щественных улучшений по сравнению с традиционными, императивными языками программирования (такими как Java, C# и C++).
Nemerle, кроме традиционного императивного програм-мирования, поддерживает функциональное программи-рование. Это выражается в наличии конструкций, упро-щающих манипуляцию функциями, построение и анализ сложных структур данных и т.п.
К сожалению, если вы не использовали возможности, присущие функциональным языкам ранее, то вам будет трудно оценить, насколько Nemerle может оказаться вам полезным в реальной повседневной работе. Данная статья призвана в неформальной форме продемонс-трировать это.
.

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

И>>Иногда для оптимизации и не такое приходится делать, например выкидывать std::vector, из-за того, что тот свой буфер зануляет.

WH>А что reserve + push_back не помогает?
Нет, не помогало. Сначала убрали вектора, а позже вообще перешли на пул выделенных буферов.

И>>Например есть строки размером от 50КБ до 5МБ, надо найти и вырезать какие-то куски без лишних релокейшинов. Все что мне нужно — хоть простой набор алгоритмов над текстовым writable буфером.

WH>Это решается умным представлением строк. Одна из возможных структур данных называется rope.
Да, оказывается я этот rope несколько лет назад реализовывал, только не знал как оно называется. Но вопрос был по С#, String + StringBuilder не покрывают даже вполне распространенных сценариев, в частности элементарного редактирования текста средних и более размеров. Вон в той же Java (откуда, я так понимаю, и были слизаны String+StringBuilder), таки появился Rope. Вот тебе и зоопарк реализаций. То, что иммутабельные строки могут быть полезны — согласен, но и должна быть возможность для нормального редактирования строк хотя бы средних размеров (нормального редактирования, а не с помощью обрубка вроде StringBuilder). И здесь иммутабельность не особо и нужна.
Re[31]: А теперь забань себя сам!
От: Erop Россия  
Дата: 04.06.09 09:11
Оценка: +1 -1
Здравствуйте, Sinclair, Вы писали:

E>>Зачем куда-то передавать сhar*, и как C# этого удаётся избежать?

S>В C# char* запрещён.
Очень хорошо и я рад за него.
А как стронние API-то вызывать при этом предлагается? Может быть всё-таки не совсем таки запрещён?
S>Речь идет о реальных библиотеках и реальном API. Эти гигабайты кода никто не будет оборачивать и переписывать.
А как же их вызывать из С#, если таки const сhar* запрещёно, а в "гигабайтах кода" в интерфейсных функциях довольно таки популярен?

S>Правильно. А почему можно сделать std::string("мама").clear()?

А почему нет? Это всего лишь вопрос к тому, как в языке устроены переменные, выражения и их взаимодействия...
Вообще не понятно, чем такое выражение
std::string("мама").clear()
вредно? Ведь такое:
std::string str( "мама" );
str.clear();
написать можно? А первое это несколько сокращённая запись второго и всё...

S>Давай посмотрим на такой же пример со строками:

S>
S>var i = "hello";
S>i += " world";
S>

S>Здесь фигурируют три строки. Сначала i указывала на строку "hello", потом была создана новая строка (путем конкатенации двух строк), и i стала указывать на эту новую строку. Сама строка "hello" (байты, на которые указывала i вначале) никак не поменялась. Это и есть семантика value-типа: значение измениться никак не может.
Ты зачем-то путаешь объекты, существующие только у тебя в голове ("заранее сконструированные числа", "значение строки") и их представление в памяти ЭВМ. Первые меняться не могут, а вторые очень даже... В С++ для того, чтобы ограничить какую-то переменную, хранящую неизменное значение, так, чтобы оно реально не могло меняться, можно использовать QV-квалификатор. В C# оказалось органичнее заиметь для этой цели другой тип. Ну и что? Это же только мелкие подробности реализации организации такого ограничения на операции с ПЕРЕМЕННОЙ. И всё. В каждом языке это делают так, как там удобно. В С удобно просто расставить модификатор const у нужных методов, а в C# приходится иметь два класса. Ну и хорошо. Пусть себе приходится. Зато там другие преимущества есть. Но ты, если я тебя верно понял, пока спорил вменяемо, утверждал, что наличие двух строк -- иммутабельного "значения" и некой фабрики по производству таких значений, это более правильно и удобно... Вот этот тезис очень странен для меня. И почему для операций с плавающей точкой нам неудобно использовать какой-то FPU_calculator, а для операций со строками -- якобы удобно StringBuilder...
Ты писал, что фишка в том, что создание копии строки дорого стоит, ну так это тогда всё в неэффективность мутабельной строки в С# упирается выходит? Потому, как в С++ удобно и легко получается COW и нет никаких мегапроблем. А для константных строк тоже нет проблем...

S>Ты, по-видимому, не понимаешь, что такое "семантика значения".

S>Да, мутабельных чисел нет нигде. Учите матчасть — это value типы. И думайте головой.
Ну я предлагаю не спорить о терминах. В данном контексте "семантика значения" -- это было ровно то, что std::vector требует от своего элемента... (иммутабельность, если ты не в курсе, не входит...)

S>Это замечательный подход. Он гарантирует тебе, что ничего полезного ты никогда не изучишь. Ты только послушай себя: "раз в С++ нет, значит не надо". Ок, хорошо. Зачем тогда весь этот ритуальный танец вокруг нового стандарта? Ведь если лямбд не было в stl, то они гарантированно не нужны.

Ну я тем, не менее изучаю что-то. Вот и у тебя прошу ПОНЯТНО, объяснить, в чём, С ТВОЕЙ точки зрения так уж хороши иммутабельные строки + билдер?
Пункт 1 -- типа так проще писать многопоточный код. Но многопоточный код, работающий с зашаренными константными данными легко писать и так и этак, поэтому я не совсем тебя понял, почему это преимущество...

S>Не от любой. Есть последовательность букв, которая ведет себя как value — от неё можно и нужно требовать иммутабельности. Если я поместил Иванова на букву И в телефонной книге, пусть он будет любезен оставаться Ивановым.

S>Контракт такой строки вполне известен: от нее можно вычислить хеш, который гарантированно будет совпадать для одинаковых строк (и всегда будет соответствовать содержимому строки); строки можно конкатенировать; можно порождать подстроку.
Ну и что? На С++ эта задача решается легко и непринуждённо. Если уж тебе так надо, чтобы его фамилия не менялась, то делаешь это поле const и всё...
Про хэш там или подстроки -- тем более нет проблем...

S>Но главное в контракте этой строки — гарантия иммутабельности. То что результат произвольной F(s) будет оставаться ровно таким же, до тех пор, пока мы не переприсвоим в s что-то еще.

Ну так и у С++ объекта та же есть особенность. Но тут есть беда, что могут быть сторонние эффекты у F(s)...
Но ПРИ ЧЁМ ТУТ ИМЕННО СТРОКИ? Это же с любыми данными может быть?

S>Ок. Это примерно как я бы наезжал на C++ "не смогли эффективно реализовать работу с данными, не разделяя их на строки и числа".

Да не смогли. А вот в перле, например, смогли...

S>Мутабельная и иммутабельная строка — разные контракты.

CString и const CString -- тоже...
Тебе в дизайне С++ строк не нравится то, что с константной строки можно легко получить неконстантную копию? Ну это же легко закрывается, если кому-то такое РЕАЛЬНО НУЖНО... А больше отличий как-то нет. Ну ещё копировать мутабельную С++ строку можно так же хорошо, как и иммутабельну. Но разве это недостаток, с которым нужно бороться?

S>Мы знаем, что строкам не нужно изменение по месту. Что если я сконструировал объект WebRequest(string url), то он может и будет полагаться на неизменность переданного адреса вплоть до вызова GetResponse().

Так пусть копирует ОБЪЕКТ строка себе и будет уверен. А как там разрулить копирование и владение буферами -- это пусть сам объект разбирается...
Но я всё равно не понимаю, ни почему не нужно, ни чем это от любого другого типа данных отличается?

E>>ПОЧЕМУ нужны иммутабельные и нет строки, но НЕ НУЖНЫ иммутабельные последовательности букв?

S>Что такое "иммутабельная последовательность букв"?
Последовательность букв, которую нельзя менять, очевидно...

S>Ок. Эти документы окажутся осмысленными, когда у читателя вырастет нужный опыт — я думаю, что это связано не с количеством извилин, а исключительно с кругозором. Ну ты вроде тут модер? Правила своего форума знаешь? Вот и оставь свои мысли о моём кругозоре при себе... Ну чиста, чтобы не нарушать твои же правила...

А то так кажется, что ты хочешь опять разозлить меня, а потом забанить... Наверное аргументы закончились?

E>>Например я могу назвать фреймворк, который был разработан после появления С++ и строки там мутабельные, так же как и числа: MFC, STL, ATL, QT... хватит?

S>Юноша, stl — это часть стандарта С++. До него вообще никаких строк в С++ не было. Ну стандарты С++ выходят время от времени. Который из них ты считаешь за "появление С++" я не знаю. Зато знаю кучу С++ кода, написанного и даже проданного задолго до 1998-го года...
Я там выделил какие фреймворки ты указал, в качестве образца ("который был разработан после появления С++")...
AFAIK STL появился после MFC, и уж подавно после С++...
Кстати, в МFC тех лет какие-то строки уже были...

S>В MFC строки — вообще кошмар проектировщика. Я уже писал в этом форуме другим упёртым фанатам — например, на тему втискивания внутрь строки всех сервисных методов, которые должны быть снаружи.

Это как-то связанно с вопросом об имуутабельности или с тем, что MFC появилась после С++?

S>В QT тут, как вроде только что писали, строки иммутабельны. Врут?

Ну врут обычно те, кто не интересуются первоисточниками... Смотри: QString и QConstString.
Насколько я понял, что именно ты понимаешь под "иммутабельностью" всё сделано мутабельно.
И совсем не так, как в С#...

S>Собственно, основной подвиг дотнета по отношению к строкам — то, что разработчики сделали так, чтобы строки вели себя как числа.

IMHO уже std::string ведут себя как числа, так же как и complex<double>, например...

S>Юноша, stl — это ... И думайте головой.

Ты вилимо не Юноша, да?
Я подозреваю, что я старше тебя...
Поэтому либо извинись, либо забань себя сам.
А разговаривать с человеком, который сам допускает нарушение своих же правил и сам потом банит собеседников, когда сказать ничего не может -- это себя не любить...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[26]: Ну ты вообще многого не видишь... ;)
От: Erop Россия  
Дата: 04.06.09 09:17
Оценка: +1
Здравствуйте, CreatorCray, Вы писали:

CC>В шарпе отобрали возможность делать что угодно с любой областью памяти — поэтому там можно надеяться на "гарантии иммутабельности".

Ну так его же и проектировали так, что бы индусы могли на нём относительно безопасно писать! Потому такой хороший язык и получился!

CC>Впрочем все равно можно дёрнуть native код и поковыряться указателем в памяти. И тогда все надежды гарантии пойдут лесом, как и в С++ случае.

Да и вообще пока у нас есть компьютер... Я вот помню как на ZX Spectrum извращались, например...

CC>Поэтому не надо тащить методы работы с C# в С++ где всё совсем по другому.

Да, и обратно не надо. У всех подходов свои сильные и слабые стороны...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[32]: Ну ты вообще многого не видишь... ;)
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.06.09 09:21
Оценка:
Здравствуйте, alexey_ma, Вы писали:
S>>Не путайте возможность и необходимость. Именно такое похабное отношение к строкам с самого начала и привело к тому, что в С++ появилось "многообразие стрингов из разных библиотек" и необходимость трахаться с их интероперабельностью.
_>Еще раз, в ваших собственных проектах можете не трахаться, административно, на основании тех или иных требований заказчика определяте какую библиотеку использовать и все вопросы по интероперабельность отпадают.
Это подростковые фантазии. В жизни не бывает "одной библиотеки", которая решает все нужные задачи. В плюсах шансы на то, что все библиотеки в проекте будут использовать одни и те же строки, приближаются к нулю очень быстро с ростом размера проекта.
_>Но как вы справедливо заметили есть еще и окружающая среда, которая часто не знакома с майкрософтом и дотнетом.
_>У меня же нет выбора и я по роду своей работы вынужден с ней трахаться. Поверьте, дотнет в таких случая не помошник, попробуйте написать на шарпе програмку получающую текст с экрана терминального эмулятора написанного неизвестными испанскими коллегами лет десять назад и не имеющим не только внешнего АРI и но и вообше какойлибо документациию.
И какое отношение отсутствие документации на терминал имеет к языку программирования? Неужели при программировании на плюсах документация волшебным образом появится из ниоткуда?
_>Я конечно могу порекомендовать клиенту поменять этот терминал на другой имеющий hllapi или комовский интерфейс который я смогу задействовать из C#. Но вы наверное догадиваетесь куда я буды послан вместе с своими требованиями, клиенту нет никакого резона менять то что учтойчиво и надежно работало за много лет до появления дотнета.
Вы, наверное не догадываетесь, но COM — далеко не всё, с чем может интероперировать шарп.
Покажите мне пример того, с чем вы интероперируете на С++, и что, по вашему, никак-никак не заработает в шарпе.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[25]: Ну ты вообще многого не видишь... ;)
От: Pavel Dvorkin Россия  
Дата: 04.06.09 09:31
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Не всё так сложно, о мой давний противник




S>1. Если объект не имеет исходящих ссылок, то недостижимость крайне легко доказывается. См. например DateTime — он тоже полностью Immutable (что гораздо лучше, чем в Java).


Естественно.

S>2. Если объект имеет исходящие ссылки, то при проектировании его достаточно убедиться, что сами они показывают только на иммутабельные объекты.


Хм. Ссылки на объекты своего собственного типа ?

public class Name
{
  Name anotherName;
  //...
}


А во-вторых, это довольно серьезное ограничение.

PD>>Отсюда ясно, что эффект от иммутабельности может быть как существенным и положительным, так и существенным и отрицательным. Если генерировать набор строк, не меняя длины исходной строки, а только заменяя в ней символы, то без иммутабельности эта задача решается на одной строке, одном буфере. С иммутабельностью мы рискуем захватить мегабайты, прежде чем проснется GC и уничтожит всю эту иммутабельную кунсткамеру. Более того, на нелюбиом тобой массиве из char (ASCIIZ то есть) эти операции можно выполнять на одном буфере даже при изменении длины строки, лишь бы только за пределы буфера не выходить.

S>Совершенно верно. К счастью, обычно автор программы достаточно хорошо себе представляет, какие операции он хочет делать с текстом и насколько часто. И если ему нужно часто вносить изменения в строку, он применяет StringBuilder.

Вот тут я бы высказался по поводу реализации. Мне в свое время она доставила массу не слишком приятных впечатлений. Например, надо мне эту самую строчку в верхний регистр перебросить. Но у StringBuilder нет ToUpper. Выходит, надо его ToString, а потом новый StringBuilder на основе этой строки. Или можно как-то обойтись и сделать все же inplace ?

char szString[N];
gets(szString);
strupr(szString);

и ни одного лишнего байта. Можно такое сделать ?
With best regards
Pavel Dvorkin
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.