label 10;
begin
var i := 20;
while true do
begin
i -= 1;
if i = 10 then break;
if i = 12 then goto 10;
continue;
10:
i -= 1;
Writeln('Here we are!')
end;
Writeln('Finish')
end.
Ложное предупреждение при компиляции:
Program1.pas(10) : Обнаружен недостижимый код
Ругается на строку после continue.
Да, этот код плохой, даже очень плохой, но он имеет право на существование без подобных “ворнингов”.
Потому что программа на самом деле работает и “достигает”:
Here we are!
Finish
Наткнулся, портируя дремучую фортрановскую программу, где метка на метке и довольно долго разбирался, кто у нас дурачок - я или компилятор. А вдруг и правда код недостижим? (там было довольно сложное условие попадания на метку)…
это довольно часто встречающаяся ситуация, очень похоже на эту:
function a:array of byte;
begin
SetLength(a,0);
end;
возвращаемое значение a не определено
это сообщение можно легко убрать написав a := a или a := nil, но вот с рекурсивной функцией это так просто не уберёшь, а когда появляется предупреждение в списке ошибок это очень мешает, отвлекается от программирования, а если привыкнуть к тому что оно появляется - не будет замечать ошибок… лично мне нравится когда панелька с ошибками и вводом/выводом авто сворачивается и в таком случае она ещё и будет разворачиваться каждый раз когда появляется предупреждение…
это страница с ошибками и поэтому предлагаю тут же: если результат функции используется в её теле подпрограммой то не показывать предупреждение о возвращаемом значении, и если в подпрограмме есть exit или стоит вызов себя же под if то не показывать предупреждение о бесконечной рекурсивности
этот код вообще не компилируется и не должен. А предупреждение SetLength(Result,0); уже не выдается. Не знаю, выложено ли исправление в релиз или нет. В любом случае в следующей версии предупреждения.
я не против результа и всегда им пользовался, но вспомнилась учительница информатики из 8 класса, когда я только узнал на практике что такое программирование и она лично предпочитала использовать название функции, а паскальABC.Net вроде бы пытается не отбегать от старых паскалей в стиле чтоб не путать учителей… ну про турбо паскаль я согласен, я изи перевожу код с C++ но мучаюсь если приходится переводить с турбо паскаля
Лямбды не хотят уживаться с переходами по меткам. С одной стороны это хорошо, как бы подталкивает держаться в рамках структурного программирования, но с другой…
"Употребление слов из четырех букв типа goto может иногда быть уместным даже в самом лучшем обществе."
Donald E.Knuth, “Structured Programming with go to statements”
Вот так программа работает.
label 10;
function f(i:integer):=i+i;
begin
//var f:integer->integer:=i->i+i;
var s:=0;
for var i:=1 to 10 do begin
if i>6 then goto 10;
s:=s+f(i);
end;
10:
Print(s)
end.
А вот так уже нет. При этом выдается диагностика, по-видимому, предназначенная не рядовому пользователю. Т.е. понятно, что это связано с реализацией лямбд, т.е. сообщение идет не по исходному тексту программы, а по преобразованному, но все же первые несколько минут я усиленно искал упомянутый “составной оператор”, благо программа была весьма внушительных размеров (портировал монстрика из Фортрана, где “мильён” меток - нормальная практика)
label 10;
//function f(i:integer):=i+i;
begin
var f:integer->integer:=i->i+i;
var s:=0;
for var i:=1 to 10 do begin
if i>6 then goto 10;
s:=s+f(i);
end;
10:
Print(s)
end.
Сообщение компилятора:
Program1.pas(7) : Переход внутрь составного оператора на метку 10 невозможен
А сюда не писать? Я туда пишу тоже временами, когда мне кажется, что это ошибка. А тут я сомневался, может это “фича, а не бага”.
И потом, туда ведь не станешь цитировать Кнута, а без этого как-то постно )))
Запретить проще всего… эх, не любите вы пользователей! )))
Вуз - отличное место работы. А если бы там еще и студентов не было…
(подслушано в коридоре вуза)
begin
Println('1'*0);
end.
Program2213.pas(2) : Ошибка времени выполнения: Значение MaxCapacity должно быть больше или равно единице. Имя параметра: maxCapacity
Справка → Классы → Переменная Self, опечатка в последнем предложении: Фактически в любом нестатическом методе перед именем любого поля и методу этого класса неявно присутствует Self.
К сожалению, в справке еще полно неточностней и опечаток. Вот, еще, к примеру:
На странице “Условная операция”, в строке var min := a < b & a : b; стоит знак & вместо ?
На странице “Подпрограммы для работы с динамическими массивами” – неточное описание параметров процедуры:
Должно быть: “Изменяет порядок элементов на противоположный в диапазоне динамического массива длины count, начиная с индекса index” (там еще и запятой не было);
+ Там же рядом:
Должно быть: “Изменяет порядок элементов на противоположный в диапазоне списка длины count, начиная с индекса index”
Раздел “Справочник по языку / Структура программы / Идентификаторы и ключевые слова” – устаревшая информация насчет обязательной латиницы:
Раздел справки “Справочник по языку / Типы данных / Процедурный тип” – ошибки в определении:
Должно быть:
В справке нет информации о новой “безопасной” форме срезов:
a?[from:to]
и
a?[from:to:step]
С справке в дереве Содержание (Contents) нет ни одного раздела или страницы, с которой была бы прямая ссылка на страницу описания директив компилятора – её можно найти только через индексированный поиск.
В свою очередь, уже на самой этой странице нет даже краткого упоминания (или ссылки) о существовании директив OpenMP, хотя есть целый раздел про это в главном дереве.
@Admin Похоже, вы не до конца с этим багом разобрались, по-прежнему чертовщина какая-то творится при попытке выполнения:
begin // Компилируется всё всегда ОК
var x := 123;
var y := object(x);
writeln(x, y); // Здесь всё без проблем печатается -> 123123
//writeln(x, object(x)); // Тут уже -> Ошибка времени выполнения: Ссылка на объект не указывает на экземпляр объекта.
writeln(x, y, object(x)); // А здесь вообще сразу вылет -> Exception processing message 0xC0000005 ...
end.
@Admin Вот еще кое-какие странности обнаружил с проверками на недостижимость кода (см. комментарии):
label _1, _2;
begin
loop 2 do
begin
writeln('In cycle A');
break;
writeln('unreachable code'); // OK, недостижимый код обнаружен
end;
loop 2 do
begin
writeln('In cycle B');
continue;;
writeln('unreachable code'); // ??? недостижимый код уже НЕ обнаруживается из-за пустого оператора выше (;)
end;
loop 2 do
begin
writeln('In cycle C');
goto _1;
var x := 'unreachable definition'; // !!! эта строка уже достижима для определения переменной и вывода её типа?
goto _2;
_1:
writeln(x); // ??? это нормально, что i=nil, а не "Неизвестная переменная x"?
end;
_2:
end.