Почему нет перегрузки оператора [] для типа Result с массивом char [] в D? - PullRequest
1 голос
/ 22 октября 2019

Я играл с std.range и std.algorithm и столкнулся со следующей проблемой.

int[] arr1 = [-1, 1, 2, 3, 5, 8];
char[] arr2 = ['a', 'b', 'c', 'd', 'e'];

auto res1 = arr.enumerate.find!(t => t[0] == 4);
auto res2 = arr1.enumerate.find!(t => t[0] == 4);

assert(typeof(res1).stringof == typeof(res2).stringof);

Теперь я хотел бы получить доступ к результату find, который является [Tuple!(ulong, "index", int, "value")(4, 5), Tuple!(ulong, "index", int, "value")(5, 8)].

writeln(res1[0][1]); // 5

Я правильно получаю 5. Теперь, если я сделаю то же самое с res2, равным [Tuple!(ulong, "index", dchar, "value")(4, 'e')]

writeln(res2[0][1]); // Error: no [] operator overload for type Result

, будет выдано исключение (почесывая голову). Не могли бы вы объяснить, почему он работает с массивом int[] и не работает с char[]?

ОБНОВЛЕНИЕ: если я вызову res2.array[0][1], это работает, но я ожидаю, что сообщение об ошибке будет более показательным.

1 Ответ

3 голосов
/ 22 октября 2019

Причина в том, что библиотека Phobos считает int [] произвольным доступом, а char [] - только последовательным доступом и, следовательно, не имеет оператора.

ОК, почему? Это то, что сообщество D называет «автодекодированием». Char [] - это строка UTF-8. Фобос, пытаясь быть полезным, преобразует эти последовательности UTF-8 в серию dchars, которые представляют кодовые точки Unicode.

Последовательности UTF-8 имеют переменную длину. Большинство текстов на английском языке имеют один байт, соответствующий одному символу на экране, но, как правило, это не так с другими языками. Например, знаки ударения могут быть представлены различными двух- или трехбайтовыми последовательностями. (и это становится еще более сложным в некоторых случаях, когда различные идентичные визуальные представления имеют разные внутренние представления - std.uni.byGrapheme является частью библиотеки Фобоса, которая призвана помочь с этим)

В любом случае, Фобос- снова пытаясь быть полезными, хотя мы все в целом все время чувствуем, что это ошибочный дизайн, оглядываясь назад, - пытается сжать эти, возможно, многобайтовые последовательности до одного dchar за раз, когда он зацикливается. Поскольку он не может знать, где находится N-й dchar, не просматривая всю строку до этой точки (поскольку каждый dchar потенциально может иметь различную длину, и вы должны проверить его, чтобы узнать размер), он не может сделать это дешево.

Так как оператор [] должен быть дешевым, O (1) операция с постоянным временем (и с постоянной памятью), эта реализация слишком сложна для подтверждения интерфейса, и вместо этого вы получите ошибку.

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

...