free pascal vs Delphi 10.3

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

free pascal vs Delphi 10.3

Сообщение AlexSky-coder » 09.05.2020 12:17:14

Всем привет, у меня есть такой вопрос вот конструкция:
Код: Выделить всё
a:array [0..4] of char = ('a','b','c','d');

эта конструкция работает как в делфи так и в фри паскаль,
а вот эта конструкция для массива работает только в делфи:
Код: Выделить всё
a:array of char = ['a','b','c','d']; 

а также в делфи есть возможно создавать переменные в теле программы:
Код: Выделить всё
procedure foo;
begin
var a:integer;
end;

будет ли когда такая возможность в free pascal?
AlexSky-coder
незнакомец
 
Сообщения: 1
Зарегистрирован: 28.04.2020 21:27:42

Re: free pascal vs Delphi 10.3

Сообщение iskander » 19.05.2020 15:04:22

AlexSky-coder писал(а):...а вот эта конструкция для массива работает только в делфи:
Код: Выделить всё
a:array of char = ['a','b','c','d']; 

В FPC 3.2 rc1 работает.
AlexSky-coder писал(а):...а также в делфи есть возможно создавать переменные в теле программы:
Код: Выделить всё
procedure foo;
begin
var a:integer;
end;

будет ли когда такая возможность в free pascal?

Лучше спросить об этом у разработчиков.
Видел обсуждение этой фичи на форуме Free Pascal(Delphi inline variables).
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: free pascal vs Delphi 10.3

Сообщение Дож » 19.05.2020 21:16:09

В рассылке разработчики говорят почти однозначное "нет"
https://lists.freepascal.org/pipermail/ ... 57496.html
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: free pascal vs Delphi 10.3

Сообщение Сквозняк » 20.05.2020 16:23:18

AlexSky-coder писал(а):а вот эта конструкция для массива работает только в делфи:

Код: Выделить всё
a:array of char = ['a','b','c','d'];


Вообще-то это противоречит паскалевской логике работы с массивами. У "резинового" массива по умолчанию длина 0 и тут в него пихают всякую каку. Если нужно пихать сразу, без установки нужной длины, то используйте для этого тип ansistring, в него и буквы и цифры лезут.
Сквозняк
энтузиаст
 
Сообщения: 1109
Зарегистрирован: 29.06.2006 22:08:32

Re: free pascal vs Delphi 10.3

Сообщение Sharfik » 20.05.2020 16:40:51

AlexSky-coder писал(а):а также в делфи есть возможно создавать переменные в теле программы:

А зачем так делать, чтобы больше проблем было? Это есть в VB, VBA и я не скажу что это очень удобно, скорее расслабляет. Все должно быть по полочкам, а Delphi позволяет делать слишком много вольностей, которые потом обращаются в баги программы. С тех пор как я переполз на Lazarus с Delphi я о программировании узнал больше, стал лучше его понимать чем до этого. Хотя читал не одну статью и учебник по программированию и конкретно Delphi.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 760
Зарегистрирован: 20.07.2013 01:04:30

Re: free pascal vs Delphi 10.3

Сообщение java73 » 22.05.2020 09:41:27

Sharfik писал(а):С тех пор как я переполз на Lazarus с Delphi я о программировании узнал больше, стал лучше его понимать чем до этого.

Согласен. В дельфи нет вообще ничего такого принципиально невозможного в лазарусе, пусть и обычными средствами. Я бы лучше проголосовал за некоторые синтаксические фичи из C# или питона. Типа тернарных операторов или унифицированных методов для стандартных типов данных.
java73
постоялец
 
Сообщения: 257
Зарегистрирован: 21.11.2013 09:08:10

Re: free pascal vs Delphi 10.3

Сообщение runewalsh » 28.05.2020 14:42:38

Sharfik писал(а):А зачем так делать, чтобы больше проблем было?

Это меняет поведение для управляемых переменных, таких как интерфейсы и record'ы с class operator Finalize: переменные, объявленные внутри begin-end, финализировались бы в конце блока, а переменные, объявленные в секции var, финализируются в конце всей процедуры. Например, удобно привязать к финализации закрытие файла или освобождение любого другого ресурса, связанного с сущностью, чтобы не заставлять пользователя каждый раз писать бойлерплейт с Open-try-finally Close-end. Так что без этой фичи нельзя сделать аналоги scoped_lock и подобных вещей, в которых важно, чтобы логика финализации выполнилась в середине процедуры, а не в конце.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: free pascal vs Delphi 10.3

Сообщение Sharfik » 29.05.2020 16:39:09

runewalsh писал(а):Это меняет поведение для управляемых переменных, таких как интерфейсы и record'ы с class operator Finalize: переменные, объявленные внутри begin-end, финализировались бы в конце блока, а переменные, объявленные в секции var, финализируются в конце всей процедуры. Например, удобно привязать к финализации закрытие файла или освобождение любого другого ресурса, связанного с сущностью, чтобы не заставлять пользователя каждый раз писать бойлерплейт с Open-try-finally Close-end. Так что без этой фичи нельзя сделать аналоги scoped_lock и подобных вещей, в которых важно, чтобы логика финализации выполнилась в середине процедуры, а не в конце.

Ни слова не понял, кроме того что это очень узкая фича, которая создаст кучу проблем конечному пользователю, поскольку программисты в большинствен случаев не будут уметь пользоваться и правильно работать с памятью. Пример кода можно? Я не вижу никаких проблем просто. Все что надо прекрасно освобождается само, то что создается через Create в любом случае должно освобождаться руками. Независимо от того в середине или конце это делать.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 760
Зарегистрирован: 20.07.2013 01:04:30

Re: free pascal vs Delphi 10.3

Сообщение runewalsh » 29.05.2020 17:27:43

Sharfik писал(а):то что создается через Create в любом случае должно освобождаться руками

Нет. :)
Sharfik писал(а):Ни слова не понял, кроме того что это очень узкая фича, которая создаст кучу проблем конечному пользователю, поскольку программисты в большинствен случаев не будут уметь пользоваться и правильно работать с памятью.

Вот именно, явное управление ресурсами (ручное освобождение объектов) гораздо сложнее и провоцирует гораздо больше ошибок. Освободить локально выделенный ресурс не из-под finally — уже ошибка. Именно чтобы упростить работу с ними, RAII-подобные штуки есть во всех современных языках.

Вот пример: https://ideone.com/GjF23I.

Используется интерфейсная переменная, автоматически подсчитывающая ссылки внутри TInterfacedObject, чтобы не заставлять пользователя писать try-finally и вызывать деструктор руками. Но с уничтожением объекта может быть связана логика, такая как закрытие эксклюзивно открытого файла, от которой может требоваться быть выполненной в середине процедуры.

С удобным RAII была бы возможность делать такие автоматические обёртки для всего — например, для захвата критической секции, потому что, опять же, выходить из неё не из-под finally — легко допускаемая ошибка, а для управляемых типов неявный finally создаётся автоматически. С inline-переменными (и, в идеале, выводом типов для них) можно было бы вместо
Код: Выделить всё
EnterCriticalSection(cs);
try
   // work
finally
   LeaveCriticalSection(cs);
end;

делать
Код: Выделить всё
begin
   var guard := TCriticalSectionScopedGuard.Create(cs);
   // work
end;

Management operators несовместимы с Delphi, но позволяют реализовать такой TCriticalSectionScopedGuard без оверхеда на создание объекта и подсчёт ссылок (впрочем, этот оверхед на удивление небольшой).
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: free pascal vs Delphi 10.3

Сообщение MylnikovDm » 04.06.2020 00:41:58

runewalsh писал(а):Вот именно, явное управление ресурсами (ручное освобождение объектов) гораздо сложнее и провоцирует гораздо больше ошибок. Освободить локально выделенный ресурс не из-под finally — уже ошибка.


Как говорил наш преподаватель программирования по поводу управлениям ресурсами: "обезьяну очень легко научить открывать кран, но практически невозможно научить его закрывать".

Если вам нужно автоматическое управление ресурсами, то Free Pascal точно не ваш язык программирования.
В больших и сложных ресурсоёмких программах нормальный результат можно получить только при ручном управлении ресурсами.
У меня богатый опыт эксплуатации всяческих систем, которые написаны на Java с автоматическим управлением памятью. В 90% случаев проблем с данными приложениями, в том числе их глухим зависанием, связано с тем, что Java-машина в очередной раз сожрала всю доступную её оперативную память и не знает, что ей делать дальше, поскольку большинство программистов на Java вообще не приучены следить за размером используемой и доступной памяти. А зачем? Оно же там где-то как-то само потом всё освободится.

Лично меня использование try-finnaly-end не напрягает. Наоборот, это делает код более читаемым, понятным и предсказуемым. Как следствие, это как раз сокращает количество ошибок, особенно сложно уловимых.

А больше ошибок в этом случае возникает только у лентяев и студентов-троечников, которые никак не могут запомнить достаточно простые схемы и шаблоны написания надёжного кода, либо им просто лень набирать "лишние символы", чтобы их код был более читаемым и понятным.
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Re: free pascal vs Delphi 10.3

Сообщение runewalsh » 04.06.2020 02:48:52

Со сборкой мусора неправильно сравнивать, т. к. ресурс освобождается детерминированно, это просто автоматизация закрытия ресурса при выходе из скоупа. В Java эквивалентом является только лишь try-with-resources.
MylnikovDm писал(а):Лично меня использование try-finnaly-end не напрягает.

Сейчас напряжёт, смотри:
Код: Выделить всё
procedure CopySrcToTwoDsts;
var
   src, dst0, dst1: TStream;
   srcStart: int64;
begin
   src := OpenSrcStream;
   try
      srcStart := src.Position;
      dst0 := OpenDst0Stream;
      try
         dst1 := OpenDst1Stream;
         try
            dst0.CopyFrom(src, 0);
            src.Position := srcStart;
            dst1.CopyFrom(src, 0);
         finally
            FreeAndNil(dst1);
         end;
      finally
         FreeAndNil(dst0);
      end;
   finally
      FreeAndNil(src);
  end;
end;

Вариант без лесенки (который обычно в Паскале и используют, чтобы уменьшить вложенность):
Код: Выделить всё
procedure CopySrcToTwoDsts;
var
   src, dst0, dst1: TStream;
   srcStart: int64;
begin
   src := nil;
   dst0 := nil;
   dst1 := nil;
   try
      src := OpenSrcStream;
      srcStart := src.Position;

      dst0 := OpenDst0Stream;
      dst1 := OpenDst1Stream;

      dst0.CopyFrom(src, 0);
      src.Position := srcStart;
      dst1.CopyFrom(src, 0);
   finally
      FreeAndNil(dst1);
      FreeAndNil(dst0);
      FreeAndNil(src);
  end;
end;

А вот как это выглядит с RAII:
Код: Выделить всё
// type IAutoClosingStream = ...

procedure CopySrcToTwoDsts;
var
   src, dst0, dst1: IAutoClosingStream;
   srcStart: int64;
begin
   src := OpenSrcStream;
   srcStart := src.Position;

   dst0 := OpenDst0Stream;
   dst1 := OpenDst1Stream;

   dst0.CopyFrom(src);
   src.Position := srcStart;
   dst1.CopyFrom(src);
end;

Ну в каком месте первые два читаемей или устойчивей к ошибкам? Наоборот, они содержат бойлерплейт, который не несёт семантической информации, поэтому ты привыкаешь пропускать его глазами. Ошибки могут возникать и не сразу, а по мере внесения изменений в код — например, банально можно добавить четвёртый объект и забыть добавить его во все нужные места (блок зануления и блок finally), и какое-то время это по случайности будет работать.

А вот ещё вариант. Ты захватываешь критическую секцию и не используешь try-finally, ведь под ней простые присваивания:
Код: Выделить всё
EnterCriticalSection(cs);
newHead^.next := head;
head := newHead;
inc(nItems);
LeaveCriticalSection(cs);

А потом в неё добавляется дополнительная операция:
Код: Выделить всё
EnterCriticalSection(cs);
if nItems >= 1000 then raise Exception.Create('Слишком много элементов в списке.');
newHead^.next := head;
head := newHead;
inc(nItems);
LeaveCriticalSection(cs);

Ой, окружающий код внезапно стал неправильным, вот незадача.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: free pascal vs Delphi 10.3

Сообщение alexs » 04.06.2020 14:06:56

runewalsh
Бездумное использование исключений - зло.
Некоторое время назад родилась мысль - что исключения - это очередная "серебрянная пуля". Как итог - возникают такие ляпсусы как последний ваш пример.

Никто не запрещал добавить проверку на валидность созданных объектов перед их использованием.
if Assigned(Stream) then
..
Структурное програмирование - тоже сильная вещь.
Создавай объекты и освобождай их в одном месте - ограни это в try-finaly
а вот логику вынеси из этого блока в отдельную процедуру/функцию
и передавай в неё заведомо валидные объекты/указатели и т.д.

Таких простеший примеров можно ещё много привести.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: free pascal vs Delphi 10.3

Сообщение haword » 04.06.2020 14:50:14

runewalsh писал(а):Со сборкой мусора неправильно сравнивать

примерно то же самое. вы объявили переменную но не зафиналили ее, а может произойти что вы и писали, произойдет исключение, и процедура не завершиться и память останется выделенной. поэтому в интерпретаторах есть отдельный процесс который проверяет все ссылки на память на валидность и очищает невалидные. в других языках этот процесс не запускается поэтому надо руками в блоках файнали освобождать память. конечно проще было бы вообще ничего не делать пускай система сама все делает. и вот после такого стиля программирования размеры программ приближаются к 100 мегабайт хотя тот же функционал ранее делали в программах в 2-3 мегабайта. а все из-за того что людям лень делать определенные вещи и все перекладывают на систему или библиотеки. и получается что написал одну строчку кода а прилинковалось к программе 20 мегабайт.
так что у всего есть свои плюсы и минусы, плюсы интерпретаторов в том что многое за программиста делает система но минусы жирные программы и медленные, а у компиляторов надо за памятью следить руками зато программы быстрее и меньше и не требуют библиотек с собой таскать определенных версий.
haword
постоялец
 
Сообщения: 301
Зарегистрирован: 02.03.2006 11:34:40

Re: free pascal vs Delphi 10.3

Сообщение MylnikovDm » 05.06.2020 01:16:47

runewalsh писал(а):Ой, окружающий код внезапно стал неправильным, вот незадача.


А разве у нас есть такие седы разработки, где любой специально написанный идиотизм всегда будет правильным?

Возможно, что я излишне старомоден, но я предпочитаю чётко видеть в коде, где и когда будут освобождаться те или иные ресурсы. И меня совершенно не напрягает количество вложенных блоков try...finally. Наоборот, по ним как раз легко определить, что забыли освободить.

Если вам нужны дополнительные удобства и сервис от компилятора по контролю за ресурсами, то существует масса других сред разработки, в которых это реализовано.
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Re: free pascal vs Delphi 10.3

Сообщение runewalsh » 05.06.2020 03:41:09

haword писал(а):вы объявили переменную но не зафиналили ее

Кого я где не зафиналил? Всё там само зафиналивается из-за работы через интерфейсы с подсчётом ссылок, в том и дело. https://ideone.com/kSOIxl.
Выше уже объяснялось, когда нужен контроль над зафиналиванием с большей гранулярностью, чем тело процедуры, и что скоупнутые переменные для этого идеально подходят.
MylnikovDm писал(а):Возможно, что я излишне старомоден, но я предпочитаю чётко видеть в коде, где и когда будут освобождаться те или иные ресурсы.

Так автоматические переменные и имеют это чёткое место — конец своей области видимости.
MylnikovDm писал(а):А разве у нас есть такие седы разработки, где любой специально написанный идиотизм всегда будет правильным?

Этот идиотизм было легко допустить, т. к. первоначальный вариант заведомо не бросал исключений, поэтому finally был необязателен.
Хорошо, когда написать неправильный код СЛОЖНЕЕ правильного.
Например, система типов не даёт присвоить несовместимые типы, или, наоборот, автоматически приводит одни типы к другим (расширяет integer до double).
Автоматические переменные аналогично сокращают пространство для ошибок.

Представь, что при использовании в выражении разных типов чисел (integer + double) integer'ы бы не расширялись до double автоматически, а выдавали мусор, и на примеры, когда из-за этого замена типа переменной ломает код, тебе бы отвечали: «Так нечего писать идиотизм, меня совершенно не напрягают ручные приведения типов, я предпочитаю всегда чётко видеть типы операндов». Для меня это точно так же звучит.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 25

Рейтинг@Mail.ru
cron