Ошибки PascalABC.NET

Для вещественных есть ln. A log для вещественных никогда и не было. Посмотрел в музейной версии 0.3. Нету.

1 лайк

Да уж…((( Это я после работы с Экселем с ума начал сходить, там log(), как и в Бейсике. Перевел задачу с макросами на Паскаль, и логарифмы оставил. А в результате что ни пытаюсь компилировать - везде ошибки лезут с комплексом. Уже полез в справку .NET - а там тоже log в библиотеке Math. Вот и запаниковал. В Паскале ведь Log() для комплексных, LogN() для заданного основания…

Я думаю, что это - моя вина. Ln пришло из Delphi, реализуется оно как Math.Log. В Delphi не было Complex, Complex.Log было просто вынесено в стандартный Log. Так и получилось. Предложение - либо переименовать комплексный Log в Ln либо сделать Log и Ln синонимами для всех типов, которые их реализуют.

Синонимы - это было бы отличное решение. Универсальное и в то же время сахарок. Переименовать комплексный Log по-моему хуже, хоть и проще: все же не все пока что можно получить из Справки и приходится временами “нырять” на сайт Microsoft за разъяснениями по библиотекам .NET. А там LOG.

Сделали Log и Ln для real и Complex.

Заодно там в качестве бонуса

var (a,b) := (1,2);

посмотрите

При нажатии мышкой на внутреннею область квадрата происходит ошибка. Из-за чего она возникает:“Program8.pas(6) : Ошибка времени выполнения: Поток не выполняется; его нельзя приостановить.”?

[details=Summary]uses graphabc; var a: real;

procedure md(x, y, z: integer); begin if (x > 100) and (x < 200) and (y > 100) and (y < 200) then readln(a); end;

begin onmousedown := md; rectangle(100, 100, 200, 200); end.[/details]

Даже не пытайтесь внутри обработчика использовать readln. Этого делать нельзя. Компилятор проверить это не может

Там - это где, в новой версии? Это вместо (var a, var b):=(1,2)?

begin
  var (x,y,z):=(3+5,1/3,-12); // вот оно, счастье!
  Println(x,y,z);
  Println(log(2)-ln(2.0),log(cplx(3,5.1)),ln(cplx(3,5.1)));
end.

А вот и несчастье, обнаруженное случайно из-за опечатки: компилятор “падает” из-за вызова неизвестной функции в Print:

begin
  Print(f(1)) // вместо f можно писать любое неизвестное компилятору имя.
end.

Ох ты, ошибка, просуществовавшая 5 часов. Спасибо что заметили - это из-за недавнего достаточно большого рефакторинга. Перевыложили

Заметил случайно, когда менял log на ln: не удалил символ и получил вызов lng

Вот за это спасибо! Щас заценим… А то надоело уже var перед каждой переменной писать.

@admin Хорошая идея с кортежным вводом, но хотелось бы, чтобы и тут работал prompt: var (x, y, z) := ReadlnInteger3('Введите X Y Z = ');

Кстати, как насчет добавить сразу и универсальный вариант ReadlnIntegerN()? И поправьте, пож., лишние пробелы при автоформатировании: var ( x , y , z ).

  1. у кортежей максимум 7 элементов(не оч удобно, но ибо нефиг кортежи для серьёзных проектов юзать)
  2. ReadlnIntegerN не будет работать потому что (integer,integer) и (integer,integer,integer) это разные типы и общи материский тип - System.Tuple, но и к нему преобразовать не получится Program1.pas(5) : Невозможно явно преобразовать тип Tuple<integer,integer> к типу System.Tuple лучше используйте массивы
function ReadlnInteger(N: cardinal): array of integer;
begin
  Result := new integer[N];
  if N <> 0 then
    for i: cardinal := 0 to N - 1 do
      Result[i] := ReadlnInteger;
end;

да и писать под каждое количество от 2 до 7 элементов(ReadlnInteger3) бесполезно, только займёт место в PABCSystem, нпмного проще так: var (x,y,z) := (ReadlnInteger('Введите X Y Z = '),ReadlnInteger,ReadlnInteger)

Почему не написать просто var a:=ReadArrInteger(ReadInteger(‘n=’)); для создания и заполнения массива?

Ну, конечно, это куда проще и нагляднее, чем было бы так: var (x, y, z) := ReadlnInteger3('Введите X Y Z = ')

Не торопитесь с выводами, коллега :wink: Вот, например, вполне себе рабочий код, хоть и не идеальный вариант, как хотелось бы:

function ReadlnIntegerN(n: integer): (integer, integer, integer, integer, integer, integer, integer);
begin
  assert((n >= 0) and (n <= 7));
  var a := new integer[7];
  ReadArrInteger(n).CopyTo(a, 0);
  Result := (a[0], a[1], a[2], a[3], a[4], a[5], a[6]);
end;

function ReadlnIntegerN(const prompt: string; n: integer): (integer, integer, integer, integer, integer, integer, integer);
begin
  write(Format(prompt, n));
  Result := ReadlnIntegerN(n)
end;

begin
  var (a, b) := ReadlnIntegerN('Введите {0} целых числа: ', 2);
  println(a, b);
  var (x, y, z) := ReadlnIntegerN('Введите X, Y, Z как целые: ', 3);
  println(x, y, z);
  var (mon, tue, wed, thu, fri, sat) := ReadlnIntegerN('Введите кол-во занятий по дням недели (Пн-Сб): ', 6);
  println(mon, tue, wed, thu, fri, sat);
  //ReadlnIntegerN(8); //::assert error
end.

Наверное, потому что не всем и не всегда нужен массив в итоге? В некоторых случаях удобнее и нагляднее работать с мнемоническими переменными, а не абстрактными индексами.

Я всё-таки ограничусь ReadInteger2 и ReadInteger3. Приглашение к вводу сделаю.

ReadlnIntegerN - какой-то совсем неправильный. На этапе выполнения невозможно задать тип (integer,integer) или (integer,integer,integer) в зависимости от n

А также ReadReal2 и ReadReal3? Очень полезно для ввода размеров двух- и трехмерных массивов, пар и троек координат точек, габаритных размеров, а также тройки параметров в циклах “от a до b с шагом h”.

Но все равно, очень жаль, что это не решит проблемы виртовского ограничения на шаг 1 (-1) в цикле, из-за которого приходится городить вот такие несуразицы для простейшей табуляции:

begin
  var (a,h,n):=(ReadReal,ReadReal,ReadInteger);
  foreach var x in n.Times.Select(i->a+i*h) do Writeln(x:7:3,x*x+0.2:9:3)
end.

Лучше так

function f(x: real) := x*x+0.2;
begin
  var (a,b) := ReadReal2;
  var N := ReadInteger;
  foreach var x in Partition(a,b,N) do
    Writeln(x:7:2,f(x):9:3)
end.

Partition как раз для этих целей

Partition - это не совсем то. Есть масса задач, когда надо протабулировать функцию от некоторого a c шагом h и до тех пор, пока очередная итерация аргумента не превысит b. А partition в общем случае изменит точки табуляции, потому что он не шаг держит, а разбивает весь интервал на равные отрезки. Например, попробуйте выполнить табуляцию для a от 0.3 с шагом 0.031 до 0.5, соблюдая именно шаг - в этой ситуации partition “ни о чем”.

В общем, это всего лишь аналог достаточно распространенного оператора цикла for x:=a to b step h (в нотации BASIC) или for x:=a step h until b еще в АЛГОЛ-60.

Хочется как-то “свернуть” цикл вида

var x:=a;
while x<=b do begin
   ...
   x+=h
   end;

Тот, на который нас обрёк Н.Вирт, кастрировав Алгол-60.

P.S. Не так давно переводил с Алгол-60 (там прекрасная библиотека исходников) процедуру обращения матрицы методом Гаусса-Жордана и когда встретился фрагмент вслух сказал очень непристойное слово, имея в виду как раз Н.Вирта…