Re[23]: Override для произвольного метода.
От: LaPerouse  
Дата: 16.12.08 11:31
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Sinclair,


S>>Прекрасный пример. Вот как раз наследование для него — худший вариант. Просто потому, что "в остальных случаях" EscapedString — вовсе не "нормальная строка". В частности, операции взятия подстроки и замены символов приведут к тому, что результат перестанет быть EscapedString.

S>>Есть пара исключений. Например, сериализация в стрим должна вести себя так же, как и в случае обычной строки. Тем не менее, говорить о каком-либо наследовании слишком смело.

LCR>Еще пожалуй ToUpper/ToLower для некоторых типов эскейпинга. Но конечно таких "совсем одинаковых" операций для обычной и необычной строки немного. С фразой "в остальных случаях ведёт как обычная строка" я конечно поторопился. Нужно добавить ещё "если перекрыть методы взятия подстроки и замены символов". Теперь уже EscapedString не столь ущербный класс, как казалось ранее См. ниже.


S>>Поэтому самый грамотный вариант — ввести новый тип EscapedString, который никак со строкой не связан.

S>>Точнее, у него должны быть определены два преобразования в строку. Примерно так:
LCR>
LCR>public class EscapedString { ... }
LCR>

S>>Естественно, неявные преобразования в строку и обратно делаются через ескейпинг. Для доступа к заексейпленным потрошкам нужно выполнить явный метод GetRawString(). Это гарантирует нам отсутствие побочных эффектов, в том числе, к примеру, невозможность случайно сконкатенировать EscapedString с UnescapedString, получив неприменимого монстра.

LCR>С одной стороны, выделяя EscapedString в отдельный класс ты ставишь крест на возможности использовать EscapedString полиморфно в классах, которые используют String, скажем библиотеку регэкспов.


Да, это может быть плохо. Собственно, это единственная причина наследоваться, больше нет. Если же смириться с отсуствием полиморфности, то есть два варианта — ввести делегирующий класс с состоянием и сервисный метод. Кому как, но в данном случае я бы предпочел именно сервисный метод.

String escapeString(String str);

Минусы — из получившейся ескейпнутой строки нельзя получить rawString без обратного преобразования

String unescapeString(String str);

Зато все просто и не нужно на каждый вдох плодить по классу.

LCR>С другой стороны, случай со String особый, потому что

LCR>1. Строки иммутабельны, следовательно все операции которые оформлены методами ведут себя как внешние функции.

Не понятно, причем здесь иммутабельность. Совершенно не обязательно быть методу иммутабельным, чтобы быть оформленным как внешняя функция с первым параметром-объектом.

LCR>1a. Следовательно, интерфейс IString пустой, и методов, которые хочется вызвать полиморфно нет.

LCR>1б. Следовательно, "методам" String можно безопасно иметь (и они имеют) наглухо прибитую зависимость от конструкторов String(...).

Соответственно из некорректной посылки — некорректный вывод.

LCR>2. Функция escape :: String -> EscapedString биективна, то есть можно как передать EscapedString во внешний код, так и получить его обратно конвертацией.


Конвертация туда-сюда не есть хорошо. Во-первых, это потеря производительности, если конечно, не поддерживается мемоизация значений, а в .net она не поддерживается. Раз уж заводить для EscepadString отдельный класс с состоянием, лучше хранить в нем rawString и выдавать escapedString по требованию, кешируя результаты, благо строка иммутабельна. Ситуация казалось бы ортогональная, и тут и там надо кешировать, но у конвертации туда-сюда есть еще один минус — эту "биективность" (ну и термин) нужно будет в будущем поддерживать.

LCR>Суммируя эти факты вынужден прийти к выводу , что да, EscapedString лучше оформить в самостоятельный класс. Замечу только, что если найдётся sealed класс, который не удовлетворяет пунктам 1 или 2, то значит sealed там стоит неудачно.


Все-таки либо-либо... Либо полиморфизм, либо наследование...
... << RSDN@Home 1.2.0 alpha 4 rev. 1089>>
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[24]: Override для произвольного метода.
От: LaPerouse  
Дата: 16.12.08 11:40
Оценка: +1
LCR>>С другой стороны, случай со String особый, потому что
LCR>>1. Строки иммутабельны, следовательно все операции которые оформлены методами ведут себя как внешние функции.

LP>Не понятно, причем здесь иммутабельность. Совершенно не обязательно быть методу иммутабельным, чтобы быть оформленным как внешняя функция с первым параметром-объектом.


Тут, конечно, надо было дописать: и иммутабельные методы могут быть полиморфными. Это абсолютно не критерий.
... << RSDN@Home 1.2.0 alpha 4 rev. 1089>>
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[24]: Override для произвольного метода.
От: Pavel Dvorkin Россия  
Дата: 16.12.08 11:48
Оценка:
Здравствуйте, Sinclair, Вы писали:

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

PD>>Предлагаю тебе сделать следующее. Выложи свои рассуждения насчет поделок на codeproject в форум MFC. Посмотрим на реакцию.
S>Павел, демократическое голосование не может служить методом решения технических вопросов.

Безусловно. Только кто тут голосование устраивал ?

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


Давай внятно. Это — заблуждения с твоей и твоих коллег точки зрения . С точки зрения других — это не заблуждения, а нормальный подход. Никаких оснований объявлять их заблуждениями у тебя нет, кроме туманных рассуждений о том, почему должно быть так, а не иначе, которые в конечном счете сводятся к тому, что это должно быть так, потому что в .Net это так. Не надо считать, что все, кто не разделяет твоое мнение, априорно заблуждаются.

S>И не стоит сводить решение вопроса о том, хорошо ли сделан класс CStringEx, к вопросу о дискредитации codeproject. На нём есть вполне вменяемые поделки, как впрочем и килотонны мусора.


А кто его пытался дискредитировать ? Не я, по крайней мере.

S>Надо применять либо собственный мозг к анализу решений, либо обращаться к людям, которые разбираются в предмете.


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

S>Членство на codeproject не даёт никаких гарантий профессионализма:


А какое членство его дает ? ИМХО никакое, даже в Академии наук.

S>

The author of CStringEX should run Purify(memory checker) on CStringEx. It particularly complains about writing out of bounds in the Delete() function.

S>(http://www.codeguru.com/forum/archive/index.php/t-42810.html)

S>Вот, к примеру, типичная проблема, которую огребает наивный пользователь унылых CxxxEx:


Во-во. Как CxxxEx — так неизбежно все они унылые. И при этом ты себя предлагаешь в арбитры. При том. что с помощью этих Cxxx сделана весьма приличная часть софта, который работает на миллионах компьютеров, в отличие от софта, написанного с помощью неунылых классов .Net, который чаще всего на одном компьютере и работает, ну на нескольких. Ничего вас не учит.

Кстати, ответь на вопрос. 10 с лишним лет Микрософт не занималась MFC. Почему они вдруг к ней вернулись ?


S>http://static.dreamincode.net/forums/showtopic5723.htm

S>Увы, за шесть лет никто не смог дать ему внятный ответ.

Я тоже не дам, да и смотреть некогда.

S>Вот что бывает с теми, кто неосторожно наследуется от чужого кода:

S>http://www.experts-exchange.com/Programming/Languages/CPP/Q_22500053.html

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


S>Зато нашел другой CStringEx. Опять же, бедному пользователю придется как-то выбирать одну из этих строк, либо руками мерджить реализации. Если бы это были хелперные функции, никакой проблемы бы не возникло. Увы, понять это люди, укушенные MFC, могут только с большим напряжением всех усилий.


Слушай, ты это серьезно ? Если да — хоть расскажи, где эти хелперные функции искать-то ? Как классы эти хелперные называются хоть ? Вот и будут все плодить эти хелперные классы, друг с другом никак не связанные (невозможно! они же sealed). Кстати, а как их (хелперные клаасы то есть) мерджить-то ? Или пусть живут как есть ? Sinclair.IsPalindrom, Dvorkin.IsRussianWord, IB.IsNonCensored ? .
With best regards
Pavel Dvorkin
Re[25]: Override для произвольного метода.
От: LaPerouse  
Дата: 16.12.08 11:55
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Слушай, ты это серьезно ? Если да — хоть расскажи, где эти хелперные функции искать-то ? Как классы эти хелперные называются хоть ? Вот и будут все плодить эти хелперные классы, друг с другом никак не связанные (невозможно! они же sealed). Кстати, а как их (хелперные клаасы то есть) мерджить-то ? Или пусть живут как есть ? Sinclair.IsPalindrom, Dvorkin.IsRussianWord, IB.IsNonCensored ? .


Очевидно там же, где и CxxxEx. Даже назвать их можешь также
... << RSDN@Home 1.2.0 alpha 4 rev. 1089>>
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[24]: Override для произвольного метода.
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.08 12:33
Оценка: 12 (2) +2
Здравствуйте, LaPerouse, Вы писали:

LP>Да, это может быть плохо. Собственно, это единственная причина наследоваться, больше нет.

Не надо этого делать.
На самом деле фишка в том, что пример плохой.
Давайте я дам хороший пример строки, который потребует наследования.

Есть так называемые "хаскелевские" строки, которые оформлены в виде связного списка фрагментов-подстрок.
Естественно, они тоже иммутабельные.
Но, в отличие от дотнетовых строк, операции конкатенации для них выполняются за O(1).
Дупа дотнета — в том, что интерфейс строки — слишком жирный.
Если бы бабушка была бы дедушкой, то регексы бы требовали не string, а, скажем, IEnumerable<char>. Или ICollection<char>.
А стринг бы их нативно реализовывал на интернальном array[char].
Тогда можно было бы сделать свою реализацию этих примитивов, построенную на списке или дереве блоков.

Увы. Всё, что можно сделать сейчас — это получить совершенно отдельный класс MyString, для которого определены операторы преобразования в стринг и обратно.
К сожалению, это не приведет ни к чему полезному — поскольку за пределами своего фреймворка мы всё равно будем вынуждены пользоваться обычным string, преобразования туда и обратно убьют всю выигранную производительность.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[25]: Override для произвольного метода.
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.08 12:50
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Безусловно. Только кто тут голосование устраивал ?

Ты. Ты апеллируешь к тому, что раз есть классы, значит они кому-то полезны.

PD>Давай внятно. Это — заблуждения с твоей и твоих коллег точки зрения . С точки зрения других — это не заблуждения, а нормальный подход. Никаких оснований объявлять их заблуждениями у тебя нет, кроме туманных рассуждений о том, почему должно быть так, а не иначе, которые в конечном счете сводятся к тому, что это должно быть так, потому что в .Net это так.

Вообще-то, Павел, я приводил конкретные агрументы. Со сравненим строчек кода и объемов лишней работы. Эти аргументы при всём желании нельзя свести к тому, что "это должно быть так, потому что в .Net это так". А вот ты как раз наоборот аргументируешь только тем, что раз какой-то индус выложил наследник CString, значит это априори хорошо, независимо от практики применения.
PD>Не надо считать, что все, кто не разделяет твоое мнение, априорно заблуждаются.

PD>А кто его пытался дискредитировать ? Не я, по крайней мере.

Ты пытался к нему апеллировать. Типа "раз вы не можете доказать, что этот сайт — отстой, значит любой код оттуда — жемчужина".

PD>Во-во. Как CxxxEx — так неизбежно все они унылые.

Конечно унылые. Я тебя носом тыкаю в проблемы, проистекающие из CxxxEx. Да, я себя предлагаю в арбитры

PD>И при этом ты себя предлагаешь в арбитры. При том. что с помощью этих Cxxx сделана весьма приличная часть софта, который работает на миллионах компьютеров, в отличие от софта, написанного с помощью неунылых классов .Net, который чаще всего на одном компьютере и работает, ну на нескольких. Ничего вас не учит.

Ну так покажи мне софт с использованием CStringEx, который работает на миллионах компьютеров. Обсудим устройство этого софта и посмотрим, можно было бы его сделать лучше без CStringEx, или его использование вызвано травмой мозга.

PD>Кстати, ответь на вопрос. 10 с лишним лет Микрософт не занималась MFC. Почему они вдруг к ней вернулись ?

Павел, меня парит давать новые ответы людям, которые не могут прочитать старые.


PD>Слушай, ты это серьезно ?

Абсолютно.
PD>Если да — хоть расскажи, где эти хелперные функции искать-то ?
А там же и искать, где ты ищешь эти CMsg, CStringEx и прочие. В чем проблема-то?

PD>Как классы эти хелперные называются хоть ? Вот и будут все плодить эти хелперные классы, друг с другом никак не связанные (невозможно! они же sealed).

Совершенно верно, несвязанные. А зачем их связывать? Они же ортогональы.
Один читает строки из ресурсов, другой занимается форматированием.

PD> Кстати, а как их (хелперные клаасы то есть) мерджить-то ? Или пусть живут как есть ? Sinclair.IsPalindrom, Dvorkin.IsRussianWord, IB.IsNonCensored ? .

Совершенно верно. Я вижу, ты начинаешь хоть медленно, но понимать. Фишка именно в том, что их не надо мерджить.
Это офигенный выигрышь во времени разработки. Когда IB добавит или исправит свою функцию, тебе не придется в своём проекте заниматься повторным мерджем.
Просто потому, что у тебя нет смердженного кода.

Я чувствую, такими темпами лет через восемь-десять ты начнешь понимать основы ООП. Ну там, разделение обязанностей, инкапсуляцию состояния.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[25]: Override для произвольного метода.
От: IB Австрия http://rsdn.ru
Дата: 16.12.08 13:01
Оценка: -1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Безусловно. Только кто тут голосование устраивал ?

Твою аппеляцию к количеству ссылок на ресурс иначе как голосованием не назовешь.

PD>Давай внятно. Это — заблуждения с твоей и твоих коллег точки зрения . С точки зрения других — это не заблуждения, а нормальный подход.

Так где эта точка зрения? Где этот нормальный подход и какие задачи он решает? Опиши это Павел, не стесняйся, мы уже десяток постов пытаемся от тебя добиться именно этого, а ты все изворачиваешься.

PD>Никаких оснований объявлять их заблуждениями у тебя нет, кроме туманных рассуждений о том, почему должно быть так, а не иначе,

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

PD> которые в конечном счете сводятся к тому, что это должно быть так, потому что в .Net это так.

Не передергивай, кроме тебя про .Net тут никто ничего не говорил.

PD> При том. что с помощью этих Cxxx сделана весьма приличная часть софта, который работает на миллионах компьютеров, в отличие от софта, написанного с помощью неунылых классов .Net, который чаще всего на одном компьютере и работает, ну на нескольких. Ничего вас не учит.

Павел, я тебя в последний раз прошу, не надо меряться, а то получится как в анекдоте про слона.

PD>Слушай, ты это серьезно ? Если да — хоть расскажи, где эти хелперные функции искать-то ? Как классы эти хелперные называются хоть ? Вот и будут все плодить эти хелперные классы, друг с другом никак не связанные (невозможно! они же sealed). Кстати, а как их (хелперные клаасы то есть) мерджить-то ? Или пусть живут как есть ? Sinclair.IsPalindrom, Dvorkin.IsRussianWord, IB.IsNonCensored ? .

Тебе еще раз Меерса процитировать, что он думает по этому поводу? Мне не сложно, ты же любишь авторитеты.. И с ним согласны и Саттер и Мак-Конел и Александреску, а этих ребят ты уж никак в поклонников .Net не зачислишь..
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[26]: Override для произвольного метода.
От: LaPerouse  
Дата: 16.12.08 13:05
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


PD>>Безусловно. Только кто тут голосование устраивал ?

S>Ты. Ты апеллируешь к тому, что раз есть классы, значит они кому-то полезны.

PD>> Кстати, а как их (хелперные клаасы то есть) мерджить-то ? Или пусть живут как есть ? Sinclair.IsPalindrom, Dvorkin.IsRussianWord, IB.IsNonCensored ? .

S>Совершенно верно. Я вижу, ты начинаешь хоть медленно, но понимать. Фишка именно в том, что их не надо мерджить.
S>Это офигенный выигрышь во времени разработки. Когда IB добавит или исправит свою функцию, тебе не придется в своём проекте заниматься повторным мерджем.
S>Просто потому, что у тебя нет смердженного кода.

Можно добавить, что выигрыш идет от того, что по сравнению с отнаследованных классом (или даже делегирующем, не суть важно) сервисные методы (обычно) делают склейку не по состоянию. В результате приобретается невозможная дотоле гибкость. Это универсальный клей, который надо научиться использовать. Не сразу это приходит, нужен некоторый опыт. До меня например где-то год доходило.
... << RSDN@Home 1.2.0 alpha 4 rev. 1089>>
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[25]: Override для произвольного метода.
От: 4058  
Дата: 16.12.08 14:47
Оценка: :)
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>С точки зрения других — это не заблуждения, а нормальный подход.


Это нормальный подход, с точки зрения начинающих программистов (в области ООП),
которые пока не в состоянии отличить хорошее от плохого.
Ничего осознание со временем прийдет, другое дело, что это время в зависимости от
индивидуальных способностей человека варьируется в очень больших пределах.

PD>Кстати, ответь на вопрос. 10 с лишним лет Микрософт не занималась MFC. Почему они вдруг к ней вернулись ?


1. Есть проекты, которые никто не станет переписывать с нуля более "кошерными" средствами, но которые тем не менее требуют доработок.
2. Осталось большое сообщество консервативно настроенных пользователей, которым просто в лом посмотреть по сторонам. Их тоже приходится поддерживать.
Re[24]: Override для произвольного метода.
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 16.12.08 16:22
Оценка:
LaPerouse,

LP>Не понятно, причем здесь иммутабельность. Совершенно не обязательно быть методу иммутабельным, чтобы быть оформленным как внешняя функция с первым параметром-объектом.


Здесь импликация в другую сторону: если тип иммутабельный, то методы ведут себя как внешние функции. Но до меня немного позже дошло, что методы могут быть полиморфными для иммутабельных объектов, см. например stateless фабрики. Мне нужно ещё немного подумать над этим моментом.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[25]: Override для произвольного метода.
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 16.12.08 16:28
Оценка:
Sinclair,

LP>>Да, это может быть плохо. Собственно, это единственная причина наследоваться, больше нет.

S>Не надо этого делать.
S>На самом деле фишка в том, что пример плохой.
S>Давайте я дам хороший пример строки, который потребует наследования.

Кстати, StringBuilder тоже sealed, но поскольку он мутабельный, то уже имеет смысл полиморфно работать с его состоянием! Скажем в EscapedStringBuilder (который :StringBuilder) перекрытие метода Append мне видится разумным решением для ситуации "хитрая строка — хитрый билдер".
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[26]: Override для произвольного метода.
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 16.12.08 19:53
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Кстати, StringBuilder тоже sealed


Он sealed скорее всего потому что его использование захардкожено в маршаллере, и он может полагаться на конкретный внутренний лейаут памяти с его состоянием. Оптимизация, короче.
... << RSDN@Home 1.2.0 alpha 4 rev. 1120 on Windows Vista 6.0.6001.65536>>
AVK Blog
Re[25]: Override для произвольного метода.
От: LaPerouse  
Дата: 17.12.08 08:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


LP>>Да, это может быть плохо. Собственно, это единственная причина наследоваться, больше нет.

S>Не надо этого делать.
S>На самом деле фишка в том, что пример плохой.
S>Давайте я дам хороший пример строки, который потребует наследования.

S>Есть так называемые "хаскелевские" строки, которые оформлены в виде связного списка фрагментов-подстрок.

S>Естественно, они тоже иммутабельные.
S>Но, в отличие от дотнетовых строк, операции конкатенации для них выполняются за O(1).
S>Дупа дотнета — в том, что интерфейс строки — слишком жирный.
S>Если бы бабушка была бы дедушкой, то регексы бы требовали не string, а, скажем, IEnumerable<char>. Или ICollection<char>.
S>А стринг бы их нативно реализовывал на интернальном array[char].
S>Тогда можно было бы сделать свою реализацию этих примитивов, построенную на списке или дереве блоков.

Да, это было бы правильно. Только это уже было бы обычной реализацией интерфейса и к наследованию реализации отношения не имело бы. Насколько я понимаю, у нас тут идет спор про sealed классы => стоит ли идти на наследование реализации ради полиморфизма. Интерфейсы — понятное дело, там все классно.

Кстати, по поводу строк, как их лучше реализовать, имхо, есть другой более лучший вариант. Что такое строка, как не обычный список символов? (То есть как образец можно посмотреть на тот же haskell и немного на std::string.) Если же хочется получить строку, как у тебя написано, "на списке или дереве блоков", то реализуешь именно эти самые деревья и блоки через интерфейс списка (который используется строкой) и подсовываешь эту реализацию тому же string. Получается еще один уровень абстракции, который отделяет алогоритмическую часть (списки) от строково-ориентированный операция (строка).

S>Увы. Всё, что можно сделать сейчас — это получить совершенно отдельный класс MyString, для которого определены операторы преобразования в стринг и обратно.

S>К сожалению, это не приведет ни к чему полезному — поскольку за пределами своего фреймворка мы всё равно будем вынуждены пользоваться обычным string, преобразования туда и обратно убьют всю выигранную производительность.

Наверное, имеется ввиду производительность работы программиста? Это да. (Операторам преобразования не обязательно делать это преобразования каждый раз, более правильно хранить raw string, об этом я писал в пред. посте).
... << RSDN@Home 1.2.0 alpha 4 rev. 1089>>
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[26]: Override для произвольного метода.
От: LaPerouse  
Дата: 17.12.08 08:14
Оценка:
Здравствуйте, LaPerouse, Вы писали:

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



LP>Кстати, по поводу строк, как их лучше реализовать, имхо, есть другой более лучший вариант. Что такое строка, как не обычный список символов? (То есть как образец можно посмотреть на тот же haskell и немного на std::string.) Если же хочется получить строку, как у тебя написано, "на списке или дереве блоков", то реализуешь именно эти самые деревья и блоки через интерфейс списка (который используется строкой) и подсовываешь эту реализацию тому же string. Получается еще один уровень абстракции, который отделяет алогоритмическую часть (списки) от строково-ориентированный операция (строка).


То есть вместо

public String implements IEnumerable<Char>
{

}


было бы

public String
{
    IEnumerable[Char] list;
    
    public String()
    {
        list = new DefaultList<Char>();
    }
    
    public String(IEnumerable[Char] list)
    {
        this.list = list;
    }
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1089>>
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[27]: Override для произвольного метода.
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.12.08 08:37
Оценка:
Здравствуйте, LaPerouse, Вы писали:
LP>>Кстати, по поводу строк, как их лучше реализовать, имхо, есть другой более лучший вариант. Что такое строка, как не обычный список символов?
Вот это — очень хороший вопрос.
Пример плохого ответа можно подсмотреть в MFC.
В Java и .Net, по крайней мере, разделили интерфейсы изменяемых и неизменяемых строк.

LP>>(То есть как образец можно посмотреть на тот же haskell и немного на std::string.) Если же хочется получить строку, как у тебя написано, "на списке или дереве блоков", то реализуешь именно эти самые деревья и блоки через интерфейс списка (который используется строкой) и подсовываешь эту реализацию тому же string. Получается еще один уровень абстракции, который отделяет алогоритмическую часть (списки) от строково-ориентированный операция (строка).

Совершенно непонятно в таком случае, что такое эта "строка". Чем она отличается от "просто списка", на основе которого она построена?
Мы опять получаем какую-то невнятицу: разработчики RegEx по-прежнему принимают на вход строку и возвращают строку.

Я вот сходу не готов накидать удачный IString для иммутабельной строки. Ну то есть, конечно же, готов, но непонятно, будет ли он удачным.
И непонятно, как защититься от любителей зависеть не от IString, а сразу от SystemString: IString.
Кроме того, большинство "военных" операций со строкой делаются через нативные вызовы. Эти нативные вызовы, естественно, построены на том, что строка — это непрерывный буфер символов. Как в свете этого сделать банальный хелпер IsNormalized для произвольного IString?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[26]: Override для произвольного метода.
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.12.08 08:54
Оценка: +1
Здравствуйте, LaPerouse, Вы писали:

LP>Наверное, имеется ввиду производительность работы программиста? Это да. (Операторам преобразования не обязательно делать это преобразования каждый раз, более правильно хранить raw string, об этом я писал в пред. посте).

Нет, речь о производительности кода. Вот я пользуюсь у себя хаскельной строкой; у меня всё хорошо, код типа

foreach(var str in stringFragments))
  joined += str;

работает шустро, потому что у меня конкатенация стоит O(1).

Но вот я вызываю какой-нибудь банальный String.Compare. А он построен на вызове в нативный код, куда передается fixed char array.
Значит, для этого вызова придется "выпрямить" строку, что стоит O(N). То же самое касается IsNormalized.
Фишка в том, что строки внутри хардкорно оптимизированы. Большинство народу, загибающего тут пальцы по поводу неудачной архитектуры дотнета, представления не имеет о том, что там "под капотом". Я могу выиграть немного на одних операциях, но тут же огребу с десятком других. И мне либо придется дублировать у себя всю подсистему win32 по работе с уникодом, либо заниматься "маршаллингом" как в примере выше.

И это всё применимо даже в гипотетическом случае изготовления своего наследника от string.
В случае же реального дотнета, моя "хаскелевская" строка доживет до первого вызова за пределы моего крошечного фреймворка. Простейшая запись в TextWriter потребует конверсии в "обычный string". Да, для таких случаев, как TextWriter, предусмотреть нарошные операции в своей строке. Но что-то более другое — запись в Label.Text к примеру — всё еще будут стоить O(N).
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[28]: Override для произвольного метода.
От: LaPerouse  
Дата: 17.12.08 09:08
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Совершенно непонятно в таком случае, что такое эта "строка". Чем она отличается от "просто списка", на основе которого она построена?


Список — это reverse, concat, replace и т п
Строка — это IString (to_lower_case, to_upper_case, asBytes)

S>Мы опять получаем какую-то невнятицу: разработчики RegEx по-прежнему принимают на вход строку и возвращают строку.


Нет, они принимают на вход IEnumerable[Char]. Просто клиентский код делает Regex.foo(str.getCharacter())

S>И непонятно, как защититься от любителей зависеть не от IString, а сразу от SystemString: IString.


Эти тонкости дотнета мне неизвестны (с .net дел не имею, читать мсдн сейчас времени нет)

S>Кроме того, большинство "военных" операций со строкой делаются через нативные вызовы. Эти нативные вызовы, естественно, построены на том, что строка — это непрерывный буфер символов. Как в свете этого сделать банальный хелпер IsNormalized для произвольного IString?


Точно также — придется релизовать интерфейс IString:

class MyString implements IString
{
    public MyString()
    {
        // непрер. буффер
        super(new Buffer());
    }
    
    public boolean isNormalized()
    {
        return true;
    }
}


public static boolean isNormalized(IString str)
{
    return str.isNormalized();
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1089>>
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[29]: Override для произвольного метода.
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.12.08 09:31
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Список — это reverse, concat, replace и т п

LP>Строка — это IString (to_lower_case, to_upper_case, asBytes)
Зачем. ToLower, ToUpper — это всего лишь хелперы для того же IEnumerable<char>:
public static IEnumerable<char> String.ToLower(this IEnumerable<char> source)
{
  foreach(char c in source)
      yield return Char.ToLower(c);
}

Всех делов-то.

LP>Нет, они принимают на вход IEnumerable[Char]. Просто клиентский код делает Regex.foo(str.getCharacter())

А зачем?
Я вот воображаю такой код:
IEnumerable<char> name = request["name"];
string strName = new string(name);
Match m = nameReqex.Match(strName.Characters);

И не понимаю, зачем нам тут Name.

LP>Эти тонкости дотнета мне неизвестны (с .net дел не имею, читать мсдн сейчас времени нет)

Это не тонкости дотнета, это философский вопрос: как заставить авторов RegEx не требовать "полный string", а обойтись уместными интерфейсами.
Хорошо там, где рулит динамика — там невозможно потребовать больше, чем реально используешь. Если кроме foreach(var character in string) ты ничего не делаешь, то по факту достаточно подать на вход "утку" с GetEnumerator<char>().
А в статике постоянно влетаешь в такие вот грабли.


LP>Точно также — придется релизовать интерфейс IString:

Я же говорю — перформанс будет чудовищный. IsNormalized внезапно потребует O(N) дополнительной памяти.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[30]: Override для произвольного метода.
От: LaPerouse  
Дата: 17.12.08 10:22
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


LP>>Список — это reverse, concat, replace и т п

LP>>Строка — это IString (to_lower_case, to_upper_case, asBytes)
S>Зачем. ToLower, ToUpper — это всего лишь хелперы для того же IEnumerable<char>:
S>
S>public static IEnumerable<char> String.ToLower(this IEnumerable<char> source)
S>{
S>  foreach(char c in source)
S>      yield return Char.ToLower(c);
S>}
S>

S>Всех делов-то.

Ну а тут будут методы-члены. Это со строкой такой пример удачный попался, ибо они обычно иммутабельные, вообще говоря возможны методы, которые деструктивны. Вот их лучше делать как члены, а не хелперы.

LP>>Нет, они принимают на вход IEnumerable[Char]. Просто клиентский код делает Regex.foo(str.getCharacter())

S>А зачем?
S>Я вот воображаю такой код:
S>
S>IEnumerable<char> name = request["name"];
S>string strName = new string(name);
S>Match m = nameReqex.Match(strName.Characters);
S>

S>И не понимаю, зачем нам тут Name.

Нет, вот так

S>
S>IString name = request["name"];
S>Match m = nameReqex.Match(name.Characters);
S>


S>Хорошо там, где рулит динамика — там невозможно потребовать больше, чем реально используешь. Если кроме foreach(var character in string) ты ничего не делаешь, то по факту достаточно подать на вход "утку" с GetEnumerator<char>().

S>А в статике постоянно влетаешь в такие вот грабли.

Для меня — не криминально. Если напрягает, тогда IString можно заставить реализовать IEnumerable. В таком случае для пользователя будет все также, как и в твоем примере, просто это будет деталью реализации, улучшающий внутренний дизайн класса.
... << RSDN@Home 1.2.0 alpha 4 rev. 1089>>
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[31]: Override для произвольного метода.
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.12.08 10:57
Оценка:
Здравствуйте, LaPerouse, Вы писали:
LP>Ну а тут будут методы-члены. Это со строкой такой пример удачный попался, ибо они обычно иммутабельные, вообще говоря возможны методы, которые деструктивны.
LP> Вот их лучше делать как члены, а не хелперы.
Не вижу никакой связи между мутабельностью и мемберами-членами.
Если требуемый эффект достижим через public интерфейс, то его крайне вредно делать членом.
По той же причине: когда я займусь своей реализацией, мне придется наследоваться, либо дублировать функциональность.

Вот смотри: возьмем стандартный HttpResponse. Он, естественно, никакой не stateless.
Есть у него, допустим, метод Redirect(Url redirectTarget).
В принципе, метод ничего военного не делает.
Это всего лишь последовательность из .SetLocation; .SetStatus; .End. Все они публичные.
Тем не менее, он засунут туда как член.
Это — совершенно неверный подход.
В этот метод захардкожено использование статус-кода 302.
Я хочу уметь делать Redirect с любым из 4х статус-кодов, описанных в RFC2616,
Как решить эту проблему?

Например, можно добавить его в наследнике HttpResponse.

Ага, теперь мне нужно найти то место, где в недрах фреймворка создаётся экземпляр HttpResponse, и заменить там класс. Ну, то есть, конечно, не заменить, а перекрыть тот метод, который создает экземпляр, в своём наследнике от HttpContext, и идти дальше искать то место, где создается экземпляр HttpContext.
Это — как раз то, чего хочет Павел Дворкин. "Дайте мне распечатанный класс, и я переверну мир".

Как бы делал я?
Можно дооборудовать каждый HttpResponse методом Redirect(Url redirectTarget, RedirectType redirectType):
public enum RedirectType
{
  MovedPermanently = 301,
  Found = 302,
    SeeOther = 303,
    RetryAt = 307
}

public static class ResponseHelper
{
  public static void Redirect(this HttpResponse response, Url redirectTarget, RedirectType redirectType)
    {
        response.Location = redirectTarget;
        response.StatusCode = redirectType;
        response.StatusText = redirectType.ToString();
        response.End();
    }
}


Это позволило бы мне в тех местах, где я раньше пользовался простым response.Redirect, писать вот так:
response.Redirect(redirectTarget, RedirectType.SeeOther);


И это никак не зависит от того, как устроен response внутри. Это никак не конфликтует с другими расширениями Response.

LP>Нет, вот так

S>>
S>>IString name = request["name"];
S>>Match m = nameReqex.Match(name.Characters);
S>>

А зачем нам тот факт, что из request приезжает IString?

LP>Для меня — не криминально. Если напрягает, тогда IString можно заставить реализовать IEnumerable. В таком случае для пользователя будет все также, как и в твоем примере, просто это будет деталью реализации, улучшающий внутренний дизайн класса.

Пока улучшения дизайна не видно.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.