Я уже писал, какие , по моему мнению, нужно наложить
ограничения на управляющую переменную (счетчик) цикла FOR.
Для удобства скопирую сюда:
Saferoll писал(а):
Еще бы наложить ограничения на переменную. Я не так радикален, чтобы как в Аде создавать переменную прямо в заголовке цикла. Но лучше бы сделать ее "как можно более локальной":
1) после FOR должен быть простой идентификатор, без всяких селекторов и квалификаторов (не элемент массива, записи или другого модуля).
2) переменная цикла FOR должна быть локальной переменной "самой локальной" процедуры, т.е. должна быть описана в разделе VAR (не в параметрах!) той процедуры, непосредственно в теле которой находится FOR
3) в блоке инициализации модуля (или в блоке финализации) может быть употреблена переменная цикла, которая описана в разделе VAR этого модуля, и эта переменная не должна быть экспортируемой.
Вот таким на мой взгляд должен быть FOR в Обероне. Собственно, всё это кроме ограничения на переменную цикла уже реализовано.
Поясню, почему считаю такие ограничения необходимыми. Переменная цикла должна изменяться только при помощи скрытого механизма, поэтому она не должна испытывать воздействия откуда-то извне. Она имеет такой же смысл, как индекс внутри оператора сумма (сигма большое) или переменная в кванторе, поэтому она "связанная переменная" - имеет смысл только внутри.
Будучи студентом, а потом и преподавателем, я наблюдал частые ошибки с оператором for в Паскале. Очень часто вызывали какую-то процедуру содержащую цикл FOR изнутри тела цикла FOR, но оба цикла использовали одну и ту же глобальную переменную в качестве счетчика. В результате значение переменной менялось весьма замысловато, и такие ошибки было трудно отследить. Причем во вложенных циклах на одном уровне такие ошибки возникали редко и легко обнаруживались, потому что заголовки в тексте располагались рядом.
Ошибки возникали потому, что в любом цикле студенты "по математической привычке" использовали индексы i,j,k или n и m, или x,y,z (смотря для какой предметной области составляли программу). Создавая подпрограмму, они в соответствии с принципом "разделяй и властвуй" не задумывались, откуда эта подпрограмма может быть вызвана и не будет ли конфликта переменных. Собственно для этого структурное (модульное) программирование и предназначено. Вот только ленились для счетчика цикла употреблять локальную переменную, а использовали для всех циклов for глобальные.
Я ввел строгое (такое же строгое, как запрет goto) правило "Использовать в циклах for для счетчика только "самую локальную" переменную". Ошибок стало меньше. Возражения об экономии памяти в стеке и таблицах компилятора отметались доводами:
1) структурность и наглядность в учебных программах важнее,
2) учебные программы далеко не достигали предела имеющихся ресурсов
3) а если достигали, экономия пары-тройки переменных для счетчиков мало что давала.
Наиболее хитрые "экономисты памяти" предлагали циклы вроде
for n:=1 to n do , где n-формальный параметр процедуры, передаваемый по значению (например, размер обрабатываемого в цикле массива). Это я тоже запретил из-за малой наглядности, что вскоре стало понятно и самим "ревнителям экономии", стоило им только заняться задачей, где требовалась размерность массива на каждой итерации.
Мой опыт убеждает, что лучше всего использовать в качестве переменной цикла FOR локальную переменную, причем самую локальную, какую возможно. Доводов против, кроме сомнительной "крохоборской" экономии и возможности применять неструктурные хакерские трюки, я не знаю. Разве что, "нестандартность" и "усложнение компилятора".
Но стандарт я ругаю уж который год, к тому же в некоторых языках наименьшая локальность переменной цикла - как раз стандарт. Например, в Аде (как уже упоминалось). Кстати, в С++ тоже можно задать счетчик цикла, локальный только в самом этом цикле:
Код: "C"
А усложнение компилятора настолько незначительное, что тоже доводом не является.