Да, старые и новые if выражения не могут быть вложены друг в друга - это дестабилизирует грамматику. В грамматике действительно в новых if не может быть ? :
Если использовать только новые или только старые, то всё ОК.
Вообще, запишите в Issue - я попытаюсь вспомнить, почему в грамматике так сделано. Скорее всего потому что смешение приводит к конфликтам в грамматике, и тогда Issue я закрою. Но если нет, попробую исправить.
Самое главное преимущество,это вложенность фигурных скобок.
Сейчас,что бы вывести “{3}”
Нужно писать много вложенных фигурных скобок,а с новой конструкцией это будет выглядеть так:
Это падение компилятора. Точнее, скорее всего, PCUReader-а.
Надо найти минимальный код и запостить в issue.
Вообще я сейчас как раз делаю программу для автоматизации поиска минимального кода:
За стабильность пока не ручаюсь, но если вам и тут лень - можно сэкономить чуть чуть сил. И не ожидайте что программа сделает всё за вас. Я ещё даже нормальный парсер не прикрутил, поэтому убирать может только целыми строчками. То есть в конце придётся дочистить чтоб найти действительно минимальный код.
Чтоб использовать:
Запустите PES.pas;
Откройте папку в которой он лежит - в ней должно было создать папку Bucket;
Положите в этот Bucket все файлы проекта (желательно без файлов вроде .pcu, .pdb и .exe) и снова запустите PES.pas;
Вам должно показать какие ошибки выдаёт при компиляции и выполнении каждого из .pas файлов. Выберите ошибку для которой хотите минимальный код и ждите. Потом в папке Log найдёте результаты каждой стадии уменьшения исходников.
P.S. Считая что падает PCUReader - скорее всего придётся добавить ещё такую программу в проект:
procedure Compile(fname: string);
begin
var psi := new System.Diagnostics.ProcessStartInfo('C:\Program Files (x86)\PascalABC.NET\pabcnetcclear.exe', fname);
psi.UseShellExecute := false;
psi.RedirectStandardOutput := true;
psi.RedirectStandardError := true;
var p := System.Diagnostics.Process.Start(psi);
p.WaitForExit;
p.StandardOutput.ReadToEnd.Println;
p.StandardError.ReadToEnd.Println;
end;
begin
loop 2 do Compile('ИмяИсходникаСОшибкой.pas');
end.
И в списке файлов при запуске PES выбрать запуск этой программы (он появится не сразу, а после того как PES выполнит её 1 раз).
Потому что чтоб читать .pcu - его надо сначала создать, то есть откомпилировать придётся 2 раза.
Предлагаю добавить подпрограммы округления до разрядов десятков, сотен, тысяч и т. д., например, так:
///Математическое округление до любого допустимого разряда.
function MR(value: real; digits: integer): real;
begin
if (digits >= 0) then Result := System.Math.Round(value, digits, System.MidpointRounding.AwayFromZero)
else Result := System.Math.Round(value / (10 ** -digits), System.MidpointRounding.AwayFromZero) * 10 ** -digits;
end;
///Математическое округление до BigInteger.
function MRBigInteger(value: real; digits: integer): BigInteger;
begin
if (digits > 0) then raise new System.ArgumentOutOfRangeException('MR: digits>0')
else if (digits = 0) then Result := TruncBigInteger(System.Math.Round(value, System.MidpointRounding.AwayFromZero))
else Result := TruncBigInteger(System.Math.Round(value / (10 ** -digits), System.MidpointRounding.AwayFromZero) * 10 ** -digits);
end;
Я не нашёл подпрограмму для округления целой части числа. Как это сделать, если это уже есть, или я неправильно понял?
Я нашёл только BigInteger.Create, который, опять же, не округляет целую часть числа, да ещё использует округление до ближайшего целого в меньшую сторону для положительных числел и в большую — для отрицательных.
А, понятно.
Только зачем вам это? Округление дробной части используется, к примеру, для вывода. Если делать округление для какой то математики - то уже и в определённой СС. Как то так:
function Round(x: real; digits, СС: integer): real;
begin
var k := СС ** digits;
Result := Round(x*k, 0) / k;
end;
begin
Round(123.456, -1, 10).Println;
end.
Потому что округление это отдельная операция. new BigInteger скорее не округляет, а отбрасывается дробную часть числа.
@Admin как насчёт добавить ту Length, которая функция, в проверку здоровья кода? По моему в современном коде правильно использовать только .Length свойство. Но на куберфоруме Length(...) - один из самых встречающихся атавизмов, на ряду с глобальными переменными.
Дело, в первую очередь, не в том что она одноимённая, а в том, что это глобальная подпрограмма, а не метод. Вызов по точке и выглядит чище, и в целом более современный.
Sqrt(...) всё ещё полезен в случаях как Sqrt(x.Sqr + y.Sqr). Если Sqrt вычисляется не для выражения в скобках (то есть, к примеру, для переменной) - конечно, лучше писать x.Sqrt.
В то же время Length(...), в любом случае, должно вызываться для переменной, потому что иначе всегда не эффективно:
if Length(s1+s2) > 5 then Println(s1+s2);
Тут будет ничем не сложнее, но значитально эффективнее, написать так:
if s1.Length + s2.Length > 5 then Println(s1+s2);
Кроме того, Length(nil) возращает 0 - и это изначальная причина, почему я начал cчитать его атавизмом. В .Net пустые строки и nil это не одно и то же. У отсутствия строки не 0 символов, а собственно отсутствие информации о их кол-ве.
Если уже не кидать исключение, как в случае .Length - надо возвращать или integer?(nil), или, хотя бы -1. Но я не думаю что Length(...) может поменяться в этом направлении, потому что его основное применение - для совместимости.
Но и поэтому же - не стоит, без особой причины, мешать его с современным кодом. Если не важна читабельность - то хотя бы для того чтоб случайно не пропустить баг, связанный с s=nil.
Подарок от Деда Мороза - классический паскаль, которого нет.
На школьное и протчее образование надежд нет. Там изучают программирование точно так же, как математику, то есть то, что было во время оно. Никто там функций от методов не отличит.
Напрасно авторы PascalABC.NET и все мы вместе с ними надеемся, что завтра в школах и выше начнут изучать современное программирование.
Я уже вторую книгу будущего года по паскалю представил на форуме.
Вот такие книги печатают издательства.