OberonCore
https://forum.oberoncore.ru/

Джоэл Сполски, Назад, к основам
https://forum.oberoncore.ru/viewtopic.php?f=27&t=1151
Страница 1 из 3

Автор:  hothing [ Пятница, 05 Сентябрь, 2008 19:08 ]
Заголовок сообщения:  Джоэл Сполски, Назад, к основам

http://russian.joelonsoftware.com/Artic ... asics.html

Интересно

Автор:  Александр Ильин [ Пятница, 05 Сентябрь, 2008 20:39 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

hothing писал(а):
Интересно
Помню, изучая Компонентный Паскаль после обычного Паскаля мне пришлось много думать о том, как же выстроить стратегию работы со строками.
С одной стороны есть LEN, а с другой стороны str$, COPY и ноль на конце...

Автор:  Vlad [ Суббота, 06 Сентябрь, 2008 00:55 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Александр Ильин писал(а):
Помню, изучая Компонентный Паскаль после обычного Паскаля мне пришлось много думать о том, как же выстроить стратегию работы со строками.
С одной стороны есть LEN, а с другой стороны str$, COPY и ноль на конце...


На самом деле все очень просто. Строки с нулем на конце нужны только для WinAPI (ну или других внешних либ). Если они возникают где-то еще, значит вы используете их не по назначению, со всеми вытекающими :)

Автор:  Info21 [ Суббота, 06 Сентябрь, 2008 01:44 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Александр Ильин писал(а):
hothing писал(а):
... изучая Компонентный Паскаль после обычного Паскаля мне пришлось много думать о том, как же выстроить стратегию работы со строками. ...

По-моему, это всё равно, что думать о том, как выстроить работу с целыми числами при наличии нескольких целочисленных типов -- разве нет?
(Мы тут про КП, не про Оберон или О-2.)

Автор:  Александр Ильин [ Суббота, 06 Сентябрь, 2008 09:57 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Vlad писал(а):
На самом деле все очень просто. Строки с нулем на конце нужны только для WinAPI (ну или других внешних либ). Если они возникают где-то еще, значит вы используете их не по назначению, со всеми вытекающими :)
Казалось бы, это так. Но стандартная процедура COPY копирует строку не целиком, а до нулевого символа. Присваивание "a := b" копирует целиком, но работает только при условии, что a и b одного типа. Если b получено в процедуру как open array, т.е. без указания типа, присваивание невозможно, остаётся либо COPY, либо самописанный цикл. Конкатенации строк (+) в Обероне[-2] вообще нет.

Проблема в том, что язык сохраняет для программиста различение между контейнером (массив символов) и содержимым (используемым объёмом - до нулевого символа). В КП признали наличие проблемы и ввели символ $, чтобы явно из контейнера вытаскивать содержимое до нуля, после чего такое содержимое сделали совместимым по присваиванию с любым контейнером, обойдя чрезмерную типобезопасность. Добавили и конкатенацию. Вот цитата из "Docu/CP-New/What is New in Component Pascal.odc": "The + operator now allows to concatenate strings. The target variable must be of sufficient length to hold the resulting string".

Видите, переменная-результат не будет, а должна иметь достаточный размер. Если я не хочу трэпа, а хочу заранее убедиться в таком предусловии или даже выделить нужную память - как мне следует поступить? Просуммировать LEN каждого из параметров и в результате выделить память с большим запасом? Или померить длину каждого из них до нуля и сложить эти значения? Я понимаю, что можно выполнить LEN(s$) для всех элементов, но по производительности это будет только хуже.

Когда я продумывал стратегию работы со строками, у меня был соблазн считать так, как предлагает Vlad и на преимущество чего указывает Сполски, - что длина строки = LEN контейнера. В этом случае ноль в конце ставить не нужно, ну разве что для общения с ОС и прочими внешними библиотеками. Однако для констант компилятор сам добавляет ноль, не спрашивая меня. Без нуля не работает COPY (Оберон) и "$" (КП) - придётся использовать SYSTEM.MOVE с присущими ему рисками и вообще импортом SYSTEM. Да и вообще, получается как минимум непоследовательность: где-то нули есть, а где-то нет.

Если уж нули нужны, то пусть лучше будут везде, подумал я. Пусть реальная длина строки будет LEN-1, с этим неудобством можно смириться, применяя одни кострукции и воздерживаясь от других (скажем, используя везде WHILE i < LEN, но не FOR i := 0 TO LEN). Всё равно это константное смещение, а не интервал - длина строки равна LEN-1, а не 0..LEN-1, как в случае если 0X завершает строку. Возвращаясь к разбору конкатенации, я должен выделить под результат число байт = (сумме LEN всех компонентов минус число компонентов) плюс один. Однако снова проблема: конкатенация не всегда будет давать всегда строку ожидаемой длины, поскольку любой 0X в середине строки будет считать завершающим. На уровне компилятора укоренено представление о том, что строка завершается нулём - так было в Обероне, так осталось в КП. Значит, конкатенация в варианте КП для меня бесполезна, всё равно надо создавать библиотечную функцию. У пользователя такой библиотеки будет возникать вопрос - в каком случае что использовать.

Есть ещё один немаловажный аспект, о котором пишет Сполски, - производительность. Гораздо дешевле размещать контейнеры фиксированного размера в стеке, чем динамической длины в куче. Здесь Оберон/КП перекладывают принятие решений на разработчика: критичные по быстродействию вещи лучше написать без динамической памяти. Учитывая это, более эффективным для конкатенации решением будет существующее: есть контейнер фиксированного размера, накидаем в него куски строк, а в конце добавим ноль. В результате добавление каждого фрагмента сопровождается двумя вычислениями длины, то есть, преимущества паскалевских строк для этой типичной операции - потеряны. И LEN ничем уже помочь не может.

В общем, я пришёл примерно к такому выводу. Работу со строками лучше вынести в [стандартную] библиотеку или полностью встроить в компилятор. Наличие в компиляторе полумер только маскирует проблему, откладывая её решение. И чем больше таких полумер заложено в компилятор, тем сложнее написать библиотеку, совместимую со всеми этими огрызками решений. В идеале строка не должна ничего общего иметь с массивом символов, достаточно предусмотреть конвертацию одного в другое, и всё. Для работы со строками должны быть свои библиотечные функции, либо - по соображениям эффективности - языковые операции. Строка и контейнер должны чётко различаться, и работа со строками должна быть воможной без оглядки на контейнер. Если хочешь работать на уровне контейнеров - работай с массивами символов. Если хочешь работать со строками, то работай с ними. В последнем случае должно работать прозрачное выделение памяти под содержимое и быть моментально доступным знание о реальной длине строки. Не думаю, что удастся полноценно совместить работу нижнего и верхнего уровня, если поместить это в библиотеку, а не в компилятор. Но это пока что только мнение.

В Обероне 2007 были какие-то подвижки на тему строк, сейчас не припомню.

Кстати, кто-нибудь знает какую-нибудь хорошую книгу или статью про эффективную работу со строками?

Автор:  Александр Ильин [ Суббота, 06 Сентябрь, 2008 10:02 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Info21 писал(а):
По-моему, это всё равно, что думать о том, как выстроить работу с целыми числами при наличии нескольких целочисленных типов -- разве нет?
Ну, какую-то аналогию найти можно, наверное. Почему-то с целыми числами у меня никаких проблем не возникало, так что лучше поясните, что вы имеете в виду. Конечно, иногда бывает "жаба давит" и думаешь, INTEGER брать или SHORTINT. А вот производительность основных операций или работы с динамической памятью для целых типов далеко не так актуальны (в моей практике).

Автор:  Сергей Оборотов [ Воскресенье, 07 Сентябрь, 2008 06:48 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Александр Ильин писал(а):
В общем, я пришёл примерно к такому выводу. Работу со строками лучше вынести в [стандартную] библиотеку или полностью встроить в компилятор.
По-хорошему, компилятор должен давать возможность переопределения реализации работы со строками по требованию.

Автор:  Info21 [ Воскресенье, 07 Сентябрь, 2008 07:50 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

GUEST писал(а):
Александр Ильин писал(а):
В общем, я пришёл примерно к такому выводу. Работу со строками лучше вынести в [стандартную] библиотеку или полностью встроить в компилятор.
По-хорошему, компилятор должен давать возможность переопределения реализации работы со строками по требованию.

На фиг, на фиг такой компилятор...

"В библиотеку, жывотное!" (С)
//ув. GUEST понимает, что призыв не к нему//

Автор:  Сергей Оборотов [ Воскресенье, 07 Сентябрь, 2008 18:04 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Info21, если Вам хотелось что-то мне сказать лично, можно было написать в ЛС. Мне это польстило бы. К сожалению, действия по изменению языка зависят не только от нас с Вами.

Автор:  Info21 [ Воскресенье, 07 Сентябрь, 2008 18:58 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

GUEST писал(а):
Info21, если Вам хотелось что-то мне сказать лично, можно было написать в ЛС. ...

Уверяю Вас, я бы так и поступил.

Автор:  Valery Solovey [ Воскресенье, 07 Сентябрь, 2008 19:39 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Александр Ильин писал(а):
В идеале строка не должна ничего общего иметь с массивом символов, достаточно предусмотреть конвертацию одного в другое, и всё... Строка и контейнер должны чётко различаться, и работа со строками должна быть воможной без оглядки на контейнер. Если хочешь работать на уровне контейнеров - работай с массивами символов. Если хочешь работать со строками, то работай с ними. В последнем случае должно работать прозрачное выделение памяти под содержимое и быть моментально доступным знание о реальной длине строки. Не думаю, что удастся полноценно совместить работу нижнего и верхнего уровня, если поместить это в библиотеку, а не в компилятор. Но это пока что только мнение.
Почему строка не должна иметь ничего общего с массивом (из сказанного выше я не понял)? И что Вы называете контейнером в таком случае? По-моему, если есть тип "строка", то он и является контейнером.

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

Автор:  hothing [ Понедельник, 08 Сентябрь, 2008 09:34 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

А по мне оптимальное решение было найдено, дла Форта (sPF). В строке хранится и длина, и оконечний нуль. Есть и еще интересное решение: хранить максимальную длину строки и реальную. Но более затратно по памяти.

Автор:  Илья Ермаков [ Понедельник, 08 Сентябрь, 2008 09:54 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Ну уж максимальную длину блока памяти хранить и гарантировать границы - об этом и говорить нечего. Куда без этого.
Увы, наша древняя PC-архитектура не имеет аппаратных средств для этого. Но она не вечна :-)

Автор:  Vlad [ Понедельник, 08 Сентябрь, 2008 16:20 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Александр Ильин писал(а):
Но стандартная процедура COPY копирует строку не целиком, а до нулевого символа.


Ну и не используйте ее, если она заточена под сишные убогие строки :)

Александр Ильин писал(а):
Присваивание "a := b" копирует целиком, но работает только при условии, что a и b одного типа. Если b получено в процедуру как open array, т.е. без указания типа, присваивание невозможно, остаётся либо COPY, либо самописанный цикл.


Дык, кто мешает написать свою Strings.Assign? Чтобы не писать цикл и чтобы не использовать COPY?

Александр Ильин писал(а):
Конкатенации строк (+) в Обероне[-2] вообще нет.


Аналогично. В библиотеку. Хотя, конечно, без перегрузки операторов грустно, но оберонщики сами хотели все писать явно :)

Александр Ильин писал(а):
Видите, переменная-результат не будет, а должна иметь достаточный размер. Если я не хочу трэпа, а хочу заранее убедиться в таком предусловии или даже выделить нужную память - как мне следует поступить?


Забить на статические массивы и использовать нормальные динамические строки :) В библиотеке. Как это сделали в C++ ;)

Александр Ильин писал(а):
У пользователя такой библиотеки будет возникать вопрос - в каком случае что использовать.


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

Александр Ильин писал(а):
Есть ещё один немаловажный аспект, о котором пишет Сполски, - производительность. Гораздо дешевле размещать контейнеры фиксированного размера в стеке, чем динамической длины в куче. Здесь Оберон/КП перекладывают принятие решений на разработчика: критичные по быстродействию вещи лучше написать без динамической памяти.


Ну и как часто вам приходится писать критические по быстродействию вещи? ;) Лично мне, например, "ускорять" строковые операции за счет отказа от динамической памяти пришлось только один раз. Это в C++, где динамическая память тормозная. А в языках с нормальным GC, выделение памяти в куче - это несколько процессорных инструкций...

Автор:  slava [ Понедельник, 08 Сентябрь, 2008 22:34 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Vlad писал(а):
Забить на статические массивы и использовать нормальные динамические строки :) В библиотеке. Как это сделали в C++ ;)
Вы имеете ввиду STL, где нет проверок на выход за диапазон? :lol:

Автор:  Vlad [ Понедельник, 08 Сентябрь, 2008 23:59 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

slava писал(а):
Vlad писал(а):
Забить на статические массивы и использовать нормальные динамические строки :) В библиотеке. Как это сделали в C++ ;)
Вы имеете ввиду STL, где нет проверок на выход за диапазон? :lol:


Да, STL, где нет трапов при копировании и конкатенации строк ;) И проблем с нулевыми символами в строке тоже нет ;)

Автор:  PGR [ Вторник, 09 Сентябрь, 2008 09:53 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Александр Ильин писал(а):
Кстати, кто-нибудь знает какую-нибудь хорошую книгу или статью про эффективную работу со строками?

Тонкости работы со строками

Автор:  slava [ Вторник, 09 Сентябрь, 2008 10:01 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

Vlad писал(а):
slava писал(а):
Vlad писал(а):
Забить на статические массивы и использовать нормальные динамические строки :) В библиотеке. Как это сделали в C++ ;)
Вы имеете ввиду STL, где нет проверок на выход за диапазон? :lol:
Да, STL, где нет трапов при копировании и конкатенации строк ;) И проблем с нулевыми символами в строке тоже нет ;)
Нет трапов, но есть crash'ы так же как и в char[].
Причем для константных строк и строк, с неизменяемым размером, все равно используется char[] (нет нагрузки на heap).

Это в чистом виде Lack of Abstraction (по Джоэлу) :wink: .

Автор:  Valery Solovey [ Вторник, 09 Сентябрь, 2008 13:55 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

PGR писал(а):
Александр Ильин писал(а):
Кстати, кто-нибудь знает какую-нибудь хорошую книгу или статью про эффективную работу со строками?

Тонкости работы со строками
По-моему, это не то, Что искал Александр. Его, скорее, интересовали принципы, а не использование конкретных инструментов конкретного языка.

Автор:  Vlad [ Вторник, 09 Сентябрь, 2008 15:03 ]
Заголовок сообщения:  Re: Джоэл Сполски, Назад, к основам

slava писал(а):
Нет трапов, но есть crash'ы так же как и в char[].


А еще в C++ оператор присваивания обозначается значком '='. Вы мне хотите рассказать про недостатки C++ или чего? Так я их и так очень хорошо знаю. У вас конкретные претензии к дизайну std::string есть, вроде тех о которых говорил Александр Ильин применительно к встроенным обероновским строкам?

slava писал(а):
Причем для константных строк и строк, с неизменяемым размером, все равно используется char[] (нет нагрузки на heap).


Где вы начитались этих отрывочных сведений? Во-первых, что там используется внутри std::string - лично дело писателей STL. Во-вторых, для коротких строк некоторые имплементации могут обходиться без использования хипа. В-третьих, для эффективных константных строк (если уж они понадобились) используют свои велосипеды с отличным от std::string дизайном, заточенным под константные операции (в частности, у такой строки просто не будет операции изменения размера).

slava писал(а):
Это в чистом виде Lack of Abstraction (по Джоэлу) :wink: .


Нет, это у вас в чистом виде lack of knowledge. Зато желания кинуть какашку хоть отбавляй :)

Страница 1 из 3 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/