Нет, конечно, зачем мне хлам?))) FPC можете попробовать сами: выберите Pascal FPC (3.0.0)
Но по-моему там все же иной синтаксис.
Нет, конечно, зачем мне хлам?))) FPC можете попробовать сами: выберите Pascal FPC (3.0.0)
Но по-моему там все же иной синтаксис.
Добрый день. Наткнулся под ALT Linux на ошибку, идентичную описанной в исходной ветке обсуждения. Что до mono-full vs mono-complete: в Альте последнего нет, как нет и libmono-system-numerics. Кто-нибудь побеждал подобное? Поделитесь, пожалуйста, рецептом.
begin
var s: Set of Integer;
Include(s, ReadInteger);
end.
Ошибка времени выполнения: System.InvalidProgramException: Среда выполнения Common Language Runtime обнаружила недопустимую программу.
Стек:
в Program4.Program.$Main()
в Program4.Program.Main()
Да, исправим.
Пока пишите
begin
var s: Set of Integer;
Include(s, ReadInteger());
end.
Спасибо
begin
var s := 1.2-[2,3];//Ошибка: Операция 'dunmin' не применима к типам real и set of integer
end.
Что за dunmin? Так и должно писать?
Напишите в Issue
“Невозможно вывести типы-параметры generic-подпрограммы ReadElements (укажите типы-параметры явно)” Или может быть я неправильно пишу эту функцию?
begin
var f1: file of integer;
Rewrite(f1, 'a.dat');
Write(f1, 1, 2, 3, 4, 5);
f1.Close;
ReadElements('a.dat').Println;//ошибка
end.
Ну, вам правильно пишет, надо указывать параметры шаблона явно:
function f1<T>: T := default(T);
begin
var a := f1<byte>;
end.
Тут уже выдаёт другую ошибку. Проблема в том что компилятор думает что вы сравниваете указатель на функцию f1 и типа byte оператором <. А затем сравниваете результат с ничем. Поэтому пишет что ожидалось выражение вместо ; то есть то с чем можно сравнить.
В этом случае нужно экранировать первый <, то есть поставить перед ним & (этот знак под семёркой в англ раскладке). Тогда компилятор не сможет считать < оператором сравнения, и всё скомпилируется правильно.
Да, так работает ReadElements&<integer>('a.dat').Println;
begin
loop 10 do
begin
var i: integer;
writeln(i);
i += 1;
end;
end.
i обнуляется только в первой итерации цикла. @Admin, это ошибка?
В1 лекции повышение квалификации преподавателей об этом что-то есть https://youtu.be/U65-SebSaj4?t=5430
Там переменной присваивается сразу новое значение, поэтому обнуление и не нужно.
А почему должно обнуляться если память выделяется один раз, потом то что туда записалось то и остается. Наверное так.
Это внутренности реализации компилятора. Знание их не должно быть обязательным для программирования.
Рассмотрим попытку написать следующий код:
begin
var i:=1;
i.Println;
begin
var i:=2; // компилятор выдает ошибку
i.Print;
Inc(i);
i.Println
end;
i.Println
end.
Ошибка следующая: Внутриблочные переменные не могут иметь те же имена, что и переменные из блока верхнего уровня
А почему, собственно? Создавая Паскаль, Н.Вирт оглядывался на языки Algol-60/68, в разработке которых он принимал участие. В языке Algol любой блок begin ... end наделялся правом управлять памятью описанных в нем объектов программы. Описали переменную - можете пользоваться. Из блока вышли - все, переменная исчезла. Не то, чтобы ее скушал какой-то сборщик мусора - она отдавалась на нужды программы и могла быть отдана под какой-то иной объект в следующем блоке. Другими словами, локализация переменных в блоке была действительно локализацией. Коллизии имен не возникало, потому что вне блока его переменные не были видны, а внутри блока локальное объявление имело приоритет. И вот это программистское счастье Н.Вирт порушил “одной левой”, потребовав все объекты программы описывать в специальном разделе. В Паскале Н.Вирта вся требуемая память выделялась компилятором разово и статически. Зато эффективно. но… неудобно. В Turbo Pascal попытались поизвращаться и создали кошмарный механизм работы с управляемой памятью. В Delphi это дело подправили и появились нормальные динамические массивы.
Я не знаю, чем руководствовались разработчики PascalАВС.NET реализовав возможность описывать переменные посредством var в любом месте программы, и не обеспечив локализацию описанных переменных в блоке. Может быть, эффективностью программы? В самом деле, если использовать механизм динамической памяти, строгая локализация потребует при каждом входе в блок выделять память, а при выходе - освобождать. Представим себе переменную, описанную внутри составного оператора во вложенном цикле… Конечно, это все так, фантазия. Разработчики, если сочтут нужным, расскажут как оно на самом деле было. Но факт остается фактом: в PascalАВС.NET память в программной единице выделяется один раз, невзирая на местонахождение var. И, если переменная не инициализирована, компилятор не делает никаких “телодвижений”. Сама среда .NET при выделении памяти всегда производит инициализацию. С этой позиции, я думаю, понятно поведение кода, который привел @Bronislav
Нет ну “почему?” - понятно. В IL коде нету внутри-блочных переменных, они всегда описываются в начале подпрограммы как в старых паскалях. Другое дело - надо всё же чётко решить:
@Admin это нормально или всё же должно быть исправлено? Возможно надо больше настаивать на том что переменные надо всегда инициализировать, потому что так:
begin
loop 10 do
begin
var i: integer := 0;
writeln(i);
i += 1;
end;
end.
Всё уже работает как ожидалось.
Зачем на этом настаивать специально? Любая переменная должна быть инициализирована перед первым обращением к ней - это основа какого угодно алгоритма. Если человеку вольно нарушать этот канон - ну, как говорится, “флаг ему в руки и трамвай навстречу” (не правда ли, я добрый?). Если он делает инициализацию явно - это уже стреляный воробей, а если полагается на особенности среды программирования, то это воробей желтоклювый, имеющий шанс после первого же выстрела стать воробьем дохлым.
В C# аналогично:
static void Main(string[] args)
{
int i;
{
int i;
}
}
Локальная переменная или параметр с именем “i” нельзя объявить в данной области, так как это имя используется во включающей локальной области для определения локальной переменной или параметра
Институт математики, механики и компьютерных наук ЮФУ, 2005–2021