Здравствуйте, а вот и снова я!
За прошедшее время я перестал валять дурака и устроился на нормальную работу. Т.е., опять пишу на Delphi под офтопик, на этот раз под Firebird (который мне теперь уже почти нравится).
Всё же, Object Pascal - это, потенциально, правильный язык, что бы о нём не говорили. Естественно, не хватает многого того, что должно быть. Не буду плакать о том, что нельзя исправить, не буду много писать о том, что можно. Напишу о том, что уже получилось исправить. Раздражала необходимость явного вызова деструктора.
Как я спасся? Ну, во-первых, если это TComponent, то можно создавать его внутри другого TComponent, и рано или поздно объект всё же будет уничтожен. Иерархическая организация памяти с именами, на самом деле, не так уж сильно уступает лисповой куче по удобству (и мы вспоминаем tcl, на котором я, наверное, строчек 50 за всю жизнь написал).
Но это и так понятно. И это плохо подходит для временных объектов внутри функций. А такие объекты зачастую нужно поместить на стек. Object Pascal не особо дружественнен в этом отношении - объекты создаются на куче. Но, поскольку Object Pascal - это всё же язык довольно эклектичный (можно даже сказать - мультипарадигменный), то прагматично-приемлемый выход нашёлся. В итоге я пишу так:
function TMyClass.myMethod;
var x:TSomeObject;
var y:TSomeOtherObject;
var fr:stackFr; // магическое заклинание
begin
fr:=mkStackFrame; // магическое заклинание
x:=TSomeObject.Create;
onStack(x); // теперь x будет уничтожен
// при выходе из функции
y:=TSomeOtherObject.Create;
onStack(y); // y будет уничтожен при выходе раньше x.
DoSomething;
AndSomethingMore;
end.
По учебнику нужно было бы писать это так:
function TMyClass.myMethod;
var x:TSomeObject; y:TSomeOtherObject;
begin
x:=TSomeObject.Create;
try
y:=TSomeOtherObject.Create;
try
DoSomething;
AndSomethingMore;
finally
FreeAndNil(y);
end;
finally
FreeAndNil(x);
end;
end;
Уровень вложенности, таким образом, растёт с каждым временным объектом. Меня от этого раньше тошнило, а теперь я избавился от этого. Конечно, платой за это является некоторая потеря скорости, но всё равно, Питону нас никогда не догнать :-) Т.е., в прикладном коде этот метод вполне применим и я им уже пользуюсь довольно массированно. Также есть и ограничение - создаваемый объект должен быть потомком TObject, но это ограничение реализации, его легко преодолеть, перекрывая функцию onStack - главное, чтобы у объекта был деструктор или что-то в этом роде.
Как это сделано - смотрите в исходник: http://ecovillage.narod.ru/pascal/uStackUtil.pas Также там реализованы special variables Лиспа. Правда, я сделал special переменные только типа variant, но ведь в лиспе вообще обычно все переменные - типа variant, и ничего.
Если кто-то скажет мне, что это - велосипед и как сделать это более грамотно - скажу спасибо. Может быть, я просто отстал от развития Object Pascal и теперь это делается как-то попроще?
А при чём же здесь open source? Я проделал небольшой тест и, если кое-что выкинуть, то модуль собирается и во FreePascal (в режиме совместимости с Delphi) и даже, вроде, работает.
В общем, так получается, что мне придётся написать кое-что для себя на Delphi, но я подумываю о том, чтобы взять вместо этого FreePascal. Поэтому, чтобы два раза не вставать, собственно переходим к вопросу: пробовал ли кто-нибудь MSEide и насколько оно жизнеспособно? Lazarus вроде как-то туго идёт, или я ошибаюсь?