А по моему вы таки не попытались понять что я написал…
procedure Test(from, &to: integer);
begin
var s := '012';
s.Substring(from-1,&to-from).Length.Println;
s[from:&to].Length.Println;
end;
begin
Test(1,4);
Test(2,4);
Test(3,4);
Test(4,4);
end.
.SubString как раз работает ожидаемо, поэтому я и привёл его как пример:
Если начинать после последнего символа но брать 0 символов - ошибки нет. Если начинать на символ дальше и брать всё равно 0 символов - ошибку уже выдаёт.
Это правильная обработка пограничного значения, принятая в современных языках, вам уже показали выше.
В dll попадают не все функции. Такое ощущение, что вы компилируете RebuildStandartModules.pas без флага /rebuild. Но во всех bat-файлах он присутствует
Чтобы из модулей в сборку попадал весь функционал, а не только используемый, нужно запускать консольный компилятор с аргументами: <полное имя .pas-файла> /rebuild
Есть разные языки. Вы показали в двух языках, в которых не так как у нас.
У нас логика простая. Есть срезы и есть безопасные срезы.
В срезах первый индекс ведет себя так как если мы обращались бы по индексу. В s=‘123’ s[4] - это выход за диапазон. s[4:], s[4:4] - это всё выход за диапазон по первому индексу. Неверно указывать первый индекс, выходящий за пределы диапазона. Если указал - исключение.
Если нужно другое поведение, используются безопасные срезы: s?[4:] s?[4:4]
Надо сказать, что у нас по поводу срезов целый семинар был. Именно там были обсуждены эти варианты, в том числе и ожидаемое поведение.
Так что указывать, что что-то по-вашему там не так - странно
Было бы проще выравнять ментальные модели для соседних языков. А так выходит как с Windows/Linux: кнопка закрытия окна, кнопки Ok/Cancel лево/право специально перепутано, чтобы затруднить переход пользователей между платформами.
При любой попытке запустить удаленно на гитхабе pabcnetc <anything>.pas /rebuild возникает исключение:
Unhandled Exception: System.IO.IOException: The handle is invalid.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
at PascalABCCompiler.ConsoleCompiler.Main(String[] initialArgs)
@adminpabcnetcclear.exe при этом работает удаленно без проблем – может быть проблема в перехвате на виртуалке гитхаба ввода/вывода консоли для создания реал-тайм лога?
Локально у меня таких ошибок не возникает, но никакой разницы с pabcnetcclear.exe (который не имеет опции /rebuild) я не вижу – PABCRtl.dll все равно получается битый:
pabcnetc использует Console.Clear. И Console.ReadKey, который не совместим с перенаправлением вывода. Зато он выводит разноцветные буквы.
Он и не рассчитан на запуск из другой программы. Для компиляции из отдельной программы - используйте или pabcnetcclear, или делайте свою программу и подключайте к ней .dll компилятора.
Но обращение то идёт к области, а не к элементу. Главное чтоб область которую представляет срез не выходила за область элементов строки. А у вас получается, что вы не разрешаете индекс в конце строки потому что “религия не позволяет”.
“Так вон оно чо, Михалыч!” Ну, наконец-то, тайна этого Бермудского треугольника разгадана! Т.е. проблема (одна из 2 основных) этой оболочки компилятора в том, что, по крайней мере в режиме /rebuild, она ищет исходники стандартных модулей только в \Lib (строго как оно лежит в репе), напрочь игнорируя при этом папку \LibSource (как оно потом уже поставляется в дистре)! И в итоге, будучи запущенной из любого места вне родной репы, втихую собирает PABCRtl.dll в режиме /rebuild в непригодном урезанном виде, читая только самый минимум готовых .pcu из папки \Lib и, похоже, не включая большую часть кода из них из соображений оптимизации (т.е. как в режиме обычной компиляции!).
По этой же причине, видимо, и в IDE сейчас нет никакой заметной разницы в результате работы между кнопками “Компилировать” и “Компилировать все”, т.е. аналога опции /rebuild. Кто-то совсем недавно тут про это спрашивал “Как оно работает и зачем оно тогда надо?”
Но, похоже, проблема элементарно решается путем поиска компилятором исходников нужных модулей сначала в тек. папке основного файла, потом в \LibSource и только затем уже в \Lib. Это позволит pabcnetc.exe полноценно функционировать откуда угодно (при наличии рядом папки \Lib и/или \LibSource).
2-ая серьезная проблема – работа с перенаправлением ввода/вывода. Может стоит реализовать опцию /rebuild в pabcnetcclear.exe (уже совместимой с перенаправлением) или проще добиться совместимости с ним pabcnetc.exe только в командном (не интерактивном!) режиме, чтобы оно работало и в батниках из-под виртуалки? А то разбираться в чужом коде и писать свою отдельную консольную оболочку компилятора при наличии уже целых 2-х официальных будет как-то странно.
class Program
{
static void Main(string[] args)
{
int[] a = new int[] { 1, 2, 3 };
Console.WriteLine(a[4..3]);
}
}
Для нас - всегда - первый индекс - это индекс элемента - это то, чему нельзя позволять выходить за пределы. Если хотите - это религия. На этапе обучения обучаемый должен запомнить - первый параметр это индекс, за пределы его изменения выходить нельзя.
Ещё раз повторюсь - хотите чтобы было по-вашему - используйте безопасный срез. Тогда человек ясно отдаёт себе отчёт, что ошибки не будет - будет пустой массив
Это когда человек себе говорит: вот так прошло на этот раз - и ладно! Алгоритм у меня дырявый - да пофигу! Все как у врачей: “Хорошо зафиксированный больной в анестезии не нуждается!”
Папка Libsource всегда была лишь для изучения исходников ну и еще для того чтобы в случае ошибки туда перенаправлялся показ компилятором строчки, где произошла ошибка. То есть, ни о какой перекомпиляции исходников из LibSource после того как приложение инсталлировано речи не идет.
Безопасно работают в частности все старые строковые функции: Pos, Insert, Delete. Они легки в изучении именно потому что не падают со страшным лязгом. Безопасные срезы - аналоги таких функций. Все споры - это попытка позиционирования срезов и безопасных срезов не так как, как их задумывали разработчики.