Да. Ставьте скобки
Можете дать ответ поподробнее? Как я показал в примере кода - if
-выражение работает внутри заголовка if
-выражения и без скобок. И с ?:
внутри заголовка ?:
, конечно, тоже.
Это не очень интуитивно… И до меня дошло что можно попробовать скобки уже только когда начал все случаи тестировать. Надо хотя бы объясняющую ошибку. Особенно в случае s5
это странно выглядит.
А то вот в тут у меня изначально был случай s3
. Пока не начал разбираться - я написал ?:
внутри ?:
, хотя если внешний тренарный оператор заменить на if
- код выглядит значительно читабельнее.
Вообще то логично предположить, что работать должно и без скобок, потому что вот в этом примере выходит так, что код для s1 эквивалентен коду для s2, а значит выражение для ветки else
в s1 считается полностью до точки с запятой. Cтранно, что для if...then...else
с тернарником в else это не так.
var s1 := if false then 1 else 2 + 3; // 5
var s2 := if false then 1 else (2 + 3); // 5
var s3 := if true then 1 else 2 + 3; // 1
var s4 := (if true then 1 else 2) + 3; // 4
выражение для ветки
else
вs1
считается полностью до точки с запятой
Дело не в потоковом чтении, а в том что у if
, как и у тренарников, приоритет ниже чем у всего остального (кроме скобок). Поэтому если скобок нет - if
-выражение, как и ?:
становится внешним узлом ещё на стадии синтаксиса.
Парсер недописали. Пользуйтесь скобками =).
Мы хотели со временем убирать ? :
Да, старые и новые 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, решил выполнить код и произошло это:
Это падение компилятора. Точнее, скорее всего, 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;
Округление до определённого порядка для 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(...)
- один из самых встречающихся атавизмов, на ряду с глобальными переменными.
И давно вызов функции, одноименной со свойством, считается атавизмом?
Дело, в первую очередь, не в том что она одноимённая, а в том, что это глобальная подпрограмма, а не метод. Вызов по точке и выглядит чище, и в целом более современный.