Ошибки PascalABC.NET

???

Почему недоразумение? Нормальный код:

type
  a = class
  public 
    function fun; virtual := 3;
  end;

begin
end.
begin
  var a := Arr(('Попов',19),('Иванов',20),('Петров',18));
  Sort(a,(x,y)->x[0]<y[0]);
  a.Println;
end.
1 лайк

Program34.pas (2,5 КБ)

Здравствуйте! Проблема незначительна, но думаю стоит обратить на нее внимание. Если включен режим подсвечивания парных операторных скобок, то происходит следующее. В программе, которую прикрепил, если выделить или нажать на слово class в строке, где находиться предобъявление класса SObject 2. SObject = class;
То выделится слово class и end в последующем описании интерфейса Component.

Короче, не правильно работает подсветка парных операторных скобок.

А началось все с вопроса моего знакомого в ВК: “Ты не знаешь как сделать так что бы в класс можно было добавлять компоненты как в юнити например добавить для обьекта компонент скрипт или бокс коллайдер?” Я написал простой пример, тот что прикрепил. А потом Мне написал знакомый что у Меня в коде, что Я прислал, почему-то описание интерфейса внутри класса и описание класса - дважды. А потом показал скринсшот с подсветкой =)

Проблема для нас тяжелая: компонент редактора не наш, и анализ скобок ведется на простейшем синтаксическом уровне. А там такие вещи не ловятся

1 лайк

Операторные скобки подсвечиваются нами, а не редактором. Редактор ничего о паскалевских конструкциях не знает. Так что ошибка исправима

Немножко странное поведение…

begin var a := log10(-5); println(a); //NaN println(a = real.NaN); //false end.

Консоль:

NaN False

Нельзя так сравнивать. NaN это не число, а его отсутствие. Надо использовать real.Nan.Equals(a)

2 лайка

Действительно, NaN - это аббревиатура от английского Not a Number )))

1 лайк
// PascalABC.NET 3.2, сборка 1353 от 27.11.2016
begin
  Writeln(ReadlnString('>').ToWords[1].Length)
end.

Компилятор не понимает такой записи - ругается на параметры ToWords. А вот так не ругается…

// PascalABC.NET 3.2, сборка 1353 от 27.11.2016
begin
  Writeln(ReadlnString('>').ToWords()[1].Length)
end.

Вот так программа работает:

// PascalABC.NET 3.2, сборка 1353 от 27.11.2016
// Внимание! Если программа не работает, обновите версию!

begin
  var dig:=['0'..'9'];
  var glas:=['a','e','i','o','u','y'];
  var sogl:set of char:=['a'..'z']-glas;
  var alpha:='0123456789abcdefghijklmnopqrstuvwxyz';
  var n:=ReadInteger('Количество символов:');
  var a:=SeqRandom(n,1,36).Select(k->alpha[k]).ToArray;
  a.Println;
  a.Where(c->c in glas).Concat(a.Where(c->c in dig)).ToArray.
    Concat(a.Where(c->c in sogl)).Println
end.

А вот так - выдает ошибку компиляции (всего лишь убрал :set of char)

Очередная странность. Или я чего-то не понимаю? Мне казалось, что когда мы делим два целых числа при помощи стандартной операции деления (/), мы получаем вещественный результат. Но вот с чем столкнулся:

Компилятор ругается на формат вывода вещественного. Причем точно на такой же формат строкой выше он не ругается. Проблема автовывода? Но если убрать формат, компиляция пройдет. При запуске задачи выясняется, что деление / срабатывает как div. Ситуация становится нормальной, если написать real§/s.

Вот код, если захочется попробовать:

begin
  var r:=Range(1,ReadInteger('n='),2);
  var p:=r.Aggregate(BigInteger(1),(i,j)->i*j);
  var s:=r.Sum;
  var a,b:integer;
  a:=5; b:=8; Writeln(a/b:0:9);
  Writeln('x=',p,'/',s,'=',p/s:0:9)
end.

Пока не понял почему так, но если заменить BigInteger(1) на 1 , то все работает как надо. Возможно что-то не так с типом BigInteger, Я не специалист )

Да, но только для небольших вводимых значений. Задайте, к примеру, 50 - и произведение уйдет в переполнение (причем, без диагностики, просто ответ будет неверный).

А вот еще одна неприятная штука. Если написать

// PascalABC.NET 3.2, сборка 1356 от 04.12.2016
begin
  var a:=Arr(2,3,-2,2,1); a.Println;
  Sort(a,(x,y)->x>y); a.Println
end.

то все нормально работает.

Но стоит поменять местами в списке Arr два последних числа…

// PascalABC.NET 3.2, сборка 1356 от 04.12.2016
begin
  var a:=Arr(2,3,-2,1,2); a.Println;
  Sort(a,(x,y)->x>y); a.Println
end.

и получаем сообщение при выполнении программы:

"e.pas(6) : Ошибка времени выполнения: Не удалось выполнить сортировку,
поскольку метод IComparer.Compare() вернул несовместимые результаты.
Либо значение не равно самому себе при сравнении, либо многократное сравнение
одного значения с другим значением дает разные результаты.
x: "0",  тип x: "Int32", IComparer: "".

Ошибка не возникает, если в Sort условие поменять на x>=y

Метод расширения integer.Downto работает неверно. В исходнике системного модуля имеется комментарий на этот счёт, но метод не исправлен.

А вообще, в чём смысл таких методов расширения, как Downto, To, Range? Чем они лучше обычных методов?

“Обычные методы” - это что? Вы чем предлагаете заменить Range или To?

Здравствуйте. Обнаружил, что пример MouseDraw.pas из \Samples\Graphics\GraphABC

// PascalABC.NET 3.2, сборка 1356 от 04.12.2016
uses GraphABC;
begin
  OnMouseDown := (x,y,mb) -> MoveTo(x,y);
  OnMouseMove := (x,y,mb) -> if mb=1 then LineTo(x,y);
end.

Выдаёт ошибку для второго lambda выражения c OnMouseMove: “Невозможно преобразовать функциональный тип в процедурный тип”

Возникло предположение, что новый синтаксис для yield может вызывать какие-нибудь нетривиальные проблемы, например с if_stmt у PascalABC.y, но так как предыдущей версии уже нет, то проверить эту идею не могу.

PS. UPDATE. На самом деле я имел в виду новый синтаксис для кортежей в версии 3.1, а не yield в версии 3.2. Но версия 3.0 почему-то даёт ошибки при компиляции, так что снова не проверить.

Метод Range уже существует. Я не про заменить спрашиваю, а про смысл. Какое отношение эти методы имеют к числовой переменной. IsOdd, IsEven - это естественно и понятно, а последовательности? Последовательности можно генерировать по аналогии с Range. Может быть, в этих методах есть какой-то глубокий смысл, которого я не вижу?

Про метод Downto я написал. Похоже, его исправлять не собираются. Вот и вопрос: а зачем он тогда, если им никто не пользуется…

Методы расширения, в отличие от обычных, позволяют составлять цепочки и это прекрасная фишка нового Паскаля. var s:=ArrRandom(ReadInteger(‘n=’),10,99).Println; Это же какая цацка! Одним оператором мы убили не двух, а целую стайку зайцев. Во-первых, не объявляли ненужной нам переменной для количества элементов и не организовывали её ввод. Во-вторых, сгенерировали массив случайных чисел указанной длины. В-третьих, вывели то, что у нас получилось. В-четвертых, у нас теперь s - целочисленная последовательность, с которой можно работать. И в-пятых, эта последовательность ведет себя прилично, т.е. не меняет значения своих элементов при повторных обращениях к ней, как это сотворила бы SeqRandom (разработчики уже объясняли “феномен”, когда q:=SeqRandom(10,10,90); s.Print; s.Print; … s.Print; порождает ряды чисел, которые совершенно различны).

Вот это все - методы расширения. В отличие от обычных методов.

И все же, я не понимаю, что означает Ваше

К числовой переменной эти методы неприменимы. Они для последовательностей и их разновидностей. Если напишете var i:integer:=Range(1,10); получите ошибку при компиляции: “Нельзя преобразовать тип IEnumerable < integer > к integer”