Лично мне не понятно, зачем перекручивать именно цикл с параметрами, да ещё с последующими дебатами неоднозначных моментов вроде
Все подобные неоднозначности для пользователя устраняются наличием строгого формального описания реализации конкретной конструкции.
Но, в любом случае, итерация с превышением параметра окончания цикла выполняться не должна, иначе будет допустима ситуация с реальным арифметическим переполнением переменной цикла: тихого переполнения – в случае с целочисленной переменной (т.е. может случайно получиться вечный цикл) или возникновения исключения – в случае с вещественной переменной.
-
Вы всегда можете определить свою функцию, которая будет вычислять число шагов, либо даже готовить нужную последовательность.
-
Вы можете написать выражение для вычисления количества повторений - что за проблема?
Вот простой пример:
function RealFor(a, b, h: real) :=
SeqWhile(a, p -> p + h, q -> h > 0 ? q <= b : q >= b);
begin
foreach var x in RealFor(3.8, 4.72, 0.1) do
Writeln(x:6:3, x * x:15:6);
(21 * '-').Println;
foreach var x in RealFor(3.15, -2.1, -0.237) do
Writeln(x:6:3, x * x:15:6)
end.
Не в одном языке программирования нет выхода за границу конечного параметра цикла.
Пофиксил Иначе при шаге 0 ваша последовательность была бы бесконечной:
function RealFor(a, b, h: real) :=
SeqWhile(a, p -> p + h, q -> h > 0 ? q <= b : (h <> 0 ? q >= b : false));
А при шаге 0 любой стандартный цикл зацикливается))) Я же делал, чтобы моделировало максимально точно. Вдруг там в теле break где-то…
PascalABC.NET не возражает против бесконечных последовательностей, поскольку их элементы все равно не хранятся.
А разве шаг 0 был допустим в языках, где for
мог иметь произвольный шаг?
Да. Ведь он мог, к примеру, возвращаться функцией или вводиться с клавиатуры. Компилятор такое не может отследить. Он и сейчас допустим, например, в VB/VBA
Так же, как while true do
Алекс, спасибо за пример, а вот насчёт “ни в одном” лучше уточнять “общепринятом современном” или “из вам известных”, потому что только на моей памяти было несколько диалектов ЯП, которые переполняли FOR. Если не ошибаюсь, были даже с защитой параметра цикла от модифицирования. Кроме того, с дробными значениями следует ожидать проблему округления (± цикл).
А не могли бы Вы привести хотя бы один? Мне казалось, я знаю достаточно именно старых, а не современных языков программирования и их диалектов.
А вот из-за нее цикл с real и изгнали из большинства современных языков. Я не встречал ни одного языка программирования, который умел бы в операторе цикла (или его аналоге) делать округление параметра цикла - разве только у Айверсона в APL.
Почему “даже”? Попробуйте в разных Бейсиках поменять руками параметр цикла for.
И еще. В языке Фортран - “короле точных вычислений” - вещественное значение в цикле с параметром было запрещено. Для пробы его разрешили в версии Fortran-77, но ужаснулись результатам и с версии Fortran-90 запретили снова.
Хм… Как-то раньше никогда не задумывался над ситуацией с шагом 0 в циклах for
в других ЯП – в голову не приходило такое попробовать. Для “вечных” циклов с каким-то альтернативным выходом или окончанием (типа break, goto, exit и т.п.) цикл for
как-то… неправильно использовать. Теоретически ведь можно было просто запретить в таких языках вход в тело цикла в такой ситуации, а при компиляции с литерным 0 в шаге – как минимум выдавать warning.
Я в курсе, что такое генератор и state machine
Нельзя - это порождает неэффективный код. Представьте, что цикл внутренний и вложен в еще несколько. На каждом проходе проверять, а не зациклится ли? В языках для серьезных расчетов это недопустимо.
Давайте себе представим задачку по отделению корней сложной, сильно осциллирующей функции, когда довольно большой интервал проходится с мелким шагом. Если “уцепили” очередной корень, циклик покидаем, а до этого мы идем, идем, идем от начала интервала с меленьким таким шажком… ну почему обязательно запрещать было цикл for ? Да, это плохое решение, поганое, но допустимое.
Не думаю, что именно это было причиной разрешения нулевого шага – особенно в интерпретируемых и скриптовых языках, или даже в языках с виртуальной машиной исполнения.
Да и в высокопроизводительных числодробилках, типа Fortrana, вряд ли это было бы ощутимым – проверка на равенство 0 – это простейшая аппаратная команда, требующая обычно 1 такт на выполнение, что гораздо лучше, чем неожиданный “вечный” цикл.
Ну так это Ваши размышления, а что было реальной причиной - этого мы никогда не узнаем. Да и не меняет это ничего.
Почему не меняет? Мы тут как бы обсуждаем плюсы и минусы внедрения подобной конструкции в Паскаль и варианты её возможного синтаксиса и реализации. В этом контексте очень полезно знать, почему в промышленных языках ранее это было реализовано именно так, а не иначе.
Я не обсуждаю. Потому что это никто не будет внедрять, ломая синтаксис языка.
– сказал человек, написавший добрую половину постов в этой теме
“За базар отвечу!” )))
Вначале я был приверженцем идеи шага и вообще вещественных переменных. Но лишь потому, что недостаточно познакомился с последовательностями. После этого я отчетливо обозначил позицию противника внесения изменений в цикл for. И сейчас все сообщения - лишь по поводу того, как и почему это не нужно. Так что все последовательно.