Замечания и предложения

Мы хотели со временем убирать ? :

Да, старые и новые if выражения не могут быть вложены друг в друга - это дестабилизирует грамматику. В грамматике действительно в новых if не может быть ? :

Если использовать только новые или только старые, то всё ОК.

Вообще, запишите в Issue - я попытаюсь вспомнить, почему в грамматике так сделано. Скорее всего потому что смешение приводит к конфликтам в грамматике, и тогда Issue я закрою. Но если нет, попробую исправить.

Значит ли это что вы хотите всё же заставить работать if-выражения в корне лямбды?

@Admin,Замените, пожалуйста, конструкцию вида

begin
  var a := 3;
  $'{a}'.Println;
end.

На

begin
  var a := 3;
  '${a}'.Println;
end.

Самое главное преимущество,это вложенность фигурных скобок. Сейчас,что бы вывести “{3}” Нужно писать много вложенных фигурных скобок,а с новой конструкцией это будет выглядеть так:

begin
  var a := 3;
  '{${a}}'.Println;
end.

Если не сложно.

Это специально, чтобы формат стал несовместим с C# ?

Вовсе нет,это для удобства.

Я использовал ReadlnReal в При пошаговом выполнении программы кнопки перехода на следующий шаг сереют и перестают быть активными. Почему сейчас при использовании появляется исключение (см. Помощь новичкам)?

Изучал http://pascalabc.net/wiki/index.php?title=События_event, решил выполнить код и произошло это:

image

Это падение компилятора. Точнее, скорее всего, PCUReader-а.
Надо найти минимальный код и запостить в issue.

Вообще я сейчас как раз делаю программу для автоматизации поиска минимального кода:


За стабильность пока не ручаюсь, но если вам и тут лень - можно сэкономить чуть чуть сил. И не ожидайте что программа сделает всё за вас. Я ещё даже нормальный парсер не прикрутил, поэтому убирать может только целыми строчками. То есть в конце придётся дочистить чтоб найти действительно минимальный код.

Чтоб использовать:

  1. Запустите PES.pas;

  2. Откройте папку в которой он лежит - в ней должно было создать папку Bucket;

  3. Положите в этот Bucket все файлы проекта (желательно без файлов вроде .pcu, .pdb и .exe) и снова запустите PES.pas;

  4. Вам должно показать какие ошибки выдаёт при компиляции и выполнении каждого из .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;

Округление до определённого порядка для real уже есть среди перегрузок Round.

А для создания такого BigInteger есть конструктор. Добавлять отдельную подпрограмму для new BigInteger(value * 10 ** n) - звучит очень странно.

Я не нашёл подпрограмму для округления целой части числа. Как это сделать, если это уже есть, или я неправильно понял?

Я нашёл только 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 скорее не округляет, а отбрасывается дробную часть числа.

##
Length('ABC').Print;
'ABC'.Length.Print;

@Admin как насчёт добавить ту Length, которая функция, в проверку здоровья кода? По моему в современном коде правильно использовать только .Length свойство. Но на куберфоруме Length(...) - один из самых встречающихся атавизмов, на ряду с глобальными переменными.

И давно вызов функции, одноименной со свойством, считается атавизмом?

Дело, в первую очередь, не в том что она одноимённая, а в том, что это глобальная подпрограмма, а не метод. Вызов по точке и выглядит чище, и в целом более современный.

Давайте тогда закидаем гнилыми помидорами вызов Sqrt(x) и будем требовать x.Sqrt, потому что

Ну и все остальные функции заодно.

1 лайк

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 и все мы вместе с ними надеемся, что завтра в школах и выше начнут изучать современное программирование.

Я уже вторую книгу будущего года по паскалю представил на форуме. Вот такие книги печатают издательства.

Оставь надежду, всяк сюда входящий…

Согласен - хорошее предложение