LINUX.ORG.RU

Яр - как правильно спроектировать структуру данных строковых типов

 ,


0

3

Ответ на Яр - какие ф-ии работы со строками включить в стандартную библиотеку? (комментарий)

http://www.sbcl.org/manual/#Unicode-Support - похоже, что в SBCL строки не содержат в себе локали (хотя они являются массивами букв и в этом твоё пожелание выполненио).

В лиспворксе тоже что-то не видно той архитектуры, к-рую ты хочешь. Есть внешние форматы, а про collation ничего нет

Т.е. ты хочешь сказать, что надо глянуть и в формат SQL, где это прописано. Привожу цитату из доки любимого сервера всех пользователей Linux, т.е.из Ms SQL.

Параметры сортировки уровня сервера...

Параметры сортировки уровня базы данных При создании или изменении базы данных можно задать параметры ее сортировки по умолчанию с помощью предложения COLLATE в инструкции CREATE DATABASE или ALTER DATABASE...

Параметры сортировки уровня столбцов... - это и есть то, что надо.

Параметры сортировки уровня выражений...

SELECT name FROM customer ORDER BY name COLLATE Latin1_General_CS_AI;  

В лиспворксе есть external-formats и есть сравнение строк для юникода, но к строке они опять же не прилеплены.

Проблема с ё представляется мне важной. Раз юникод кривой, мы будем от него абстрагироваться.

Если вы знаете иной ЯП, где задача приклейки локали к строкам решена, то дайте знать.

Я сразу могу сказать про такие грабли: «Смесь french с нижегородским» - как сравнивать такую строку и как привести её к верхнему регистру? Очевидно, строка многоязычна и у неё не может быть такого атрибута, как локаль. Если локаль приклеена к букве, то это уже легче.

Пока у меня ничего не вырисовывается, разве только вот такое:

Письменность - система, охватывающая все вопросы представления
строк в компьютере: кодировка строк в виде массивов, сравнение,
приведение регистра, определение языка, изображение на экране.
Как минимум, есть три письменности: юникод, koi-8r, GB_18030
(если я правильно понял смысл последнего). 

Литера - абстрактная структура метаданных. Её атрибуты
  Письменность
  Номер (необязательно)
  Абстрактный глиф
  Понятное людям описание
  Языки, в к-рых может присутствовать
   
Кодировка - способ превращения литер или строк из литер в
массивы цифр и обратн в рамках одной письменности

Внешний формат - способ преобразования письменностей и/или кодировок.

В этой структуре пока не определен тип данных «строка» и не решён вопрос про «смесь french с нижегородским». Вопрос: правильно или нет?

★★★★★

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

dzidzitop ★★ ()

Раз юникод кривой

Уже придумали лучше?

где задача приклейки локали к строкам решена

Зачем это делать? Храним всё в utf(8/16/32) и не мучаемся.

RazrFalcon ★★★★★ ()
Ответ на: комментарий от RazrFalcon

Раз юникод кривой

Уже придумали лучше?

Юникод кривой потому что не решает проблем. В частности с коллациями — некоторая их часть описана, но они все работают только в пределах локали. Что делать с текстами, в которых есть текст на нескольких языках — неизвестно. Кроме того все языки программирования по умолчанию полностью забивают на коллаторы вообще, используют порядок символов юникода, а этот список кривой. В нём заглавная «Ё» находится до А, а строчная «ё» находится после «я».

где задача приклейки локали к строкам решена

Зачем это делать? Храним всё в utf(8/16/32) и не мучаемся.

Локали ничего общего с кодировками не имеют. Не позорься. Из кодировок пока ничего лучше utf-8 не придумали, но и он не идеален. К примеру, почему в ряде языков разные кодепоинты, рисующие одинаковые символы должны расцениваться как одинаковые, а в части — разные? Почему есть множество кодов перевода строки и как их правильно сравнивать? Что делать с неразрывными пробелами и прочими проблемными символами? Всё это просто переваливается на конечного программиста, хотя можно было просто не вносить эту чушь в стандарт изначально.

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

anonymous ()
Ответ на: комментарий от RazrFalcon

Я правильно понимаю, что задача полученния энной буквы строки в utf-8 имеет сложность О(N)? Если да, то в моём представлении это не похоже на «не мучаться».

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от anonymous

В нём заглавная «Ё» находится до А, а строчная «ё» находится после «я».

Ну это, конечно, непригодно к применению.

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

По-моему, здесь есть два выхода:

- привязывать к строке регионы языка, как это делается в текстовых редакторах

- определить такую «письменность», чтобы в ней а датское отличалось от а гренландского. По сути это то же, что и привязка языка (или коллации) к каждому отдельному символу (в Яре я называю символы литерами, поскольку символ в лиспе - это нечто совсем другое, но пусть будут символы).

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от den73

А что вы предлагаете? Вот мне нужна строка, в которой пол теста на русском, а половина на японском. Как вы решите эту задачу с KOI8-R?

Строки - боль. И никакого нормального решения ещё не придумали, и вряд ли придумают.

utf-8 имеет сложность О(N)

Да, но SSE хорошо помогает.

RazrFalcon ★★★★★ ()
Последнее исправление: RazrFalcon (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

Да, но SSE хорошо помогает.

Для меня это никогда не аргумент.

А что вы предлагаете?

utf8 - далеко не единственная кодировка даже в рамках юникода. Есть, например, utf-16, utf-32. utf-32 вроде не страдает от этой проблемы.

den73 ★★★★★ ()
Ответ на: комментарий от RazrFalcon

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

den73 ★★★★★ ()
Ответ на: комментарий от den73

Utf-32 не решает почти никаких проблем. Единственное, что он решает так это делает одинаковым размер одного кодпоинта в байтах, но один символ всё равно может состоять из разного количества кодпоинтов, более того, один и тот-же символ можно собрать из разных кодпоинтов. Всё та-же «Ё». Стандарт говорит, что если к «Е» прибавить кодпоинт двух точек, то должна получиться такая-же «Ё», как и обычная однокодепоинтная (по крайней мере после нормализации). И таких ловушек миллион, весь стандарт сплошное минное поле. Сейчас все эти проблемы просто сваливают на прикладного программиста, в «строках» нет практически ничего, что может помочь с этим беспределом. А для «строк» которые нити так и вовсе нужно гарантировать, чтобы никаких преобразований или коллаций не проводилось вовсе, как лежат в памяти байты так и должны лежать.

anonymous ()
Ответ на: комментарий от den73

utf-32 вроде не страдает от этой проблемы.

Конкретно от этой - нет. Но в unicode есть ещё 100500 подводных камней.

Ну и тут очень сложный вопрос вида: O(n) + 1B vs O(1) + 4B

RazrFalcon ★★★★★ ()
Ответ на: комментарий от RazrFalcon

Понял. Печальная картина и одновременно возможность. Каковы подходы к облегчению жизни программиста, какие библиотеки написаны для русского языка на эту тему (или для наборов языков, включая русский)?

den73 ★★★★★ ()
Ответ на: комментарий от den73

Кстати, есть один язык, который долгое время разрабатывался с оглядкой на полную поддержку Юникода и всех его подводных камней. К сожалению, это PHP6. Можешь попробовать попросить у его создателей наработки. Они конечно те ещё евреи, но может быть тебе повезёт, вряд-ли Зенду этот мусор сильно нужен.

anonymous ()
Ответ на: комментарий от den73

Я же говорю, посмотри Emacs MULE. Несколько языков в одной строке работает, китайский и японский различаются. Можно легко добавить и поле язык. Единицей текста является глиф (который может состоять из нескольких кодоточек юникода).

monk ★★★★★ ()
Ответ на: комментарий от monk

Я услышал и посмотрю. Но всё же одно дело текстовый редактор, а другое - ЯП.

А неужели в 1С нет нормальной поддержки русского языка?

den73 ★★★★★ ()
Ответ на: комментарий от den73

А неужели в 1С нет нормальной поддержки русского языка?

Русского — есть. Локаль едина на сеанс работы, определяется параметрами пользователя. Языки поддерживаются только те, которые в 1С (русский, китайский, вьетнамский, немецкий, английский и ещё где-то дюжина). ё и й если вставлять композитные, собирает в правильные односимвольные.

monk ★★★★★ ()
Ответ на: комментарий от monk

А у них своя локаль или они опираются на системную? Просто если на системную, то вопрос сводится уже к тому, как в Линуксе настраивается локаль и правильно ли там сортируется ё.

den73 ★★★★★ ()
Ответ на: комментарий от den73

А у них своя локаль или они опираются на системную

Своя. И поддерживает только те языки, которые есть в 1С. Зато эта поддержка нормальная. Например, http://v8.1c.ru/overview/Term_000000301.htm

monk ★★★★★ ()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

Спасибо, прекрасный текст про уродов, аж вдохновляет. И про 1С отличные новости. 1С - велик и могуч и нужно ориентироваться на него (хотя, возможно, я ещё чего-то не знаю). Хотя в целом я-то думал написать 5-7 функций работы со строками и бодро переключиться на другие темы. А тут какая-то бездна.

den73 ★★★★★ ()
Ответ на: комментарий от den73

Хотя в целом я-то думал написать 5-7 функций работы со строками и бодро переключиться на другие темы.

Вам придётся потратить кучу времени, чтобы реализовать хотя бы toLower/toUpper/reverse.

RazrFalcon ★★★★★ ()
Ответ на: комментарий от den73

Но всё же одно дело текстовый редактор, а другое - ЯП.

У текстовых редакторов ещё в 10 раз больше боли.

RazrFalcon ★★★★★ ()
Ответ на: комментарий от RazrFalcon

Ну я не знаю, мне казалось раньше, что SBCL поддерживает юникод:

526 >(sb-unicode:unicode< "ё" "ж")
T
528 >(sb-unicode:unicode< "е" "ё")
T
529 >(sb-unicode:unicode< "Е" "Ё")
T
530 >(sb-unicode:unicode< "Ё" "Ж")
T
531 >(sb-unicode:uppercase "ёрш твою меть")
"ЁРШ ТВОЮ МЕТЬ"
И я уже давно общаюсь между клиентом, сервером и консолью по utf-8. В tk действительно есть проблемы.

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

sb-unicode:uppercase

Тогда хорошо. Базовые вещи с нуля делать не придётся. Странно, что string-upcase в CL поломан.

monk ★★★★★ ()
Ответ на: комментарий от RazrFalcon

Кстати, раз уж разговор за юникод зашёл, есть какой-нибудь класс безопасных символов в юникоде? Чтобы не было переменных с именами типа «an​*̶͑̾̾​̅ͫ͏̙̤g͇̫͛͆̾ͫ̑͆l͖͉̗̩̳̟̍ͫͥͨe̠̅s».

monk ★★★★★ ()
Ответ на: комментарий от monk

класс безопасных символов в юникоде

А как это можешь себе представить? К любой букве можно добавить черточку , волнистую линию или точк(у|и). И даже не только к букве, а к знаку =,|,~ и тому подобному. И это будет являтся с точки зрения unicode - ВЕРНЫМ.

Atlant ★★★★★ ()
Ответ на: комментарий от Atlant

а вообще, если это ядро|библиотека ЯП, то стоит изобрести несколько внутренних структур с неявной(хотя можно и явной) конвертированием между ними.
Структуру для хранения и структуру для работы посимвольной работы с элементом структуры на адрес хранилища. Возможно с пересечениями типа union.
Если по быстрому, то:

struct 
{
	Size_T      StructSize;
	NativeWord  Type; // type union struct
	NativeWord  CapacityByte; // may be delete
	NativeWord  LengthByte;
	union {
		struct {
			CharsetType CharsetType;
			ByteChar * First;
		}
		struct {
			UTF16Char * First;
		}
		struct {
			UTF32Char * First;
		}
	}
   
}


Естественно не всё учёл. Это по идее самый минимум, который можно будет расширять, в том числе динамически - путем создание своих элементов union.

Atlant ★★★★★ ()
Ответ на: комментарий от Atlant

А как это можешь себе представить?

1. Для языка алфавит известен. Если расширить юникод до хранения языка на диапазоны символов, то можно проверять, что, например, в немецком буквы «и» нет.

2. Ограничить черточки и прочее только алфавитно-цифровыми базами.

И это будет являтся с точки зрения unicode - ВЕРНЫМ.

В UNIX тоже любая последовательность байтов является верным именем файла. Но в POSIX 1-2008 определено «переносимое имя файла».

monk ★★★★★ ()
Ответ на: комментарий от monk

Если расширить юникод до хранения языка на диапазоны символов

Это уже скорее не unicode, а некое другое понятие. Поскольку unicode - это скорее набор изображений символов всех алфавитов без разделение по итальянский,немецкий, английский, французский и т.д. .

Atlant ★★★★★ ()
Ответ на: комментарий от Atlant

Это уже скорее не unicode, а некое другое понятие. Поскольку unicode - это скорее набор изображений символов всех алфавитов без разделение по итальянский,немецкий, английский, французский и т.д. .

В юникоде есть нужная подсистема: https://en.wikipedia.org/wiki/Variant_form_(Unicode)

В рамках своей системы язык/редактор вполне можно использовать.

Если в файле один язык, то комментарий по типу vi/emacs.

monk ★★★★★ ()
Ответ на: комментарий от den73

Я думаю string-upcase в SBCL не поломан, а сделан так, чтобы быстро работал.

Похоже, чтобы соответствовал ANSI CL: «each character of the result string is produced by applying the function char-upcase to the corresponding character of string».

Вот пример, где наличие стандарта хуже его отсутствия.

monk ★★★★★ ()
Ответ на: комментарий от monk

есть какой-нибудь класс безопасных символов в юникоде?

ASCII :)

buddhist ★★★★★ ()
Ответ на: комментарий от monk

Хз. Вон в Swift весь юникод разрешён. Можно хоть эмодзи использовать.

RazrFalcon ★★★★★ ()
Ответ на: комментарий от Aswed

Для быстрого доступа к code points, но не к видимым символам. Для этого всё равно придётся разбирать графемные кластеры, что не O(1).

ilammy ★★★ ()

ё

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

annulen ★★★★★ ()
Ответ на: комментарий от den73

Это дорого по перформансу, поэтому графемными кластерами обычно оперируют только бибилотеки для шейпинга (harfbuzz)

annulen ★★★★★ ()
Ответ на: комментарий от den73

А есть ли представление строки в виде массива графемных кластеров?

MULE

monk ★★★★★ ()
Ответ на: комментарий от annulen

Это дорого по перформансу

Почему? Если со строкой действительно надо что-то делать на основании позиций, то единожды разобрать в массив графем дешевле, чем на каждую операцию пробегать с начала строки.

monk ★★★★★ ()
Ответ на: комментарий от monk

Операции поиска и замены работают на уровне code point'ов, а не графемных кластеров. К тому же, в огромном количестве кода даже этого не требуется, строки хранятся, передаются и сравниваются как единое целое, т.е. как байты

Пожалуй единственные случаи, когда нужны графменые кластеры - это шейпинг текста и редактирование на экране с помощью курсора

annulen ★★★★★ ()
Ответ на: комментарий от annulen

Ну я так понял, что ё нормализуется, даже если оно введено в виде е и двух точек. Но тогда по сути (для частного случая русского языка) нормализация - это и есть превращение в графемный кластер. Также не соглашусь насчёт шейпинга. Вот у меня простой форматный вывод, и размер поля ограничен. Если не поместилось, нужно вывести: «Здравствуйте, дорогая радиопередача. Меня зовут Вася Иванов. Хочу передать привет на морскую вахту своему папе. Я уже большой и не боюсь спать один в темноте, а вот мама боится и поэтому спит с дядей Те...»

Так вот если в конце стояло ё, е вывелось, а палки потерялись, «Тё» превратиться в «Те» - это плохо. Т.е. это вроде и шейпинг текста, но в CL такие задачи могут возникнуть абсолютно везде, т.к. есть *print-length* .

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

Т.е. как-то слёту кажется, что графемные кластеры - это, с прикладной точки зрения и есть то, с чем надо работать. А байты - это костыли.

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.