Зачем два механизма ограничений?

Проектирование и разработка идеального средства программирования.

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

Пожалуйста, прочтите верхний пост, и скажите какой подход к дизайну языка лучше.

Лучше как сейчас
10
53%
Лучше так, как сейчас, и никак иначе!
2
11%
Лучше без private и strict (но с остальными секциями)
4
21%
Мне пофиг
1
5%
Лучше убрать interface и implementation
2
11%
 
Всего голосов : 19

Re: Зачем два механизма ограничений?

Сообщение Лекс Айрин » 26.10.2015 10:22:13

Mirage писал(а):Лекс Айрин - такое ощущение, что Вы чего-то начитались не того.


Угу... например, книг по теории ООП.

Добавлено спустя 13 минут:
vitaly_l писал(а):Поэтому я "сдаюсь" без "боя" :roll: и признаю каждого из вас - правым. :evil:


ну... я могу написать примерный расклад по паскале подобному языку... это, как раз не трудно. Только он уже не будет ООП... хотя... если урезать некоторые возможности.... и отличия от классического объектного паскаля не так уж велики.

Добавлено спустя 4 минуты 27 секунд:
vitaly_l писал(а):Соответственно полное избавление от interface, implementation и объект получается компактный в одном флаконе.


Угу.. только вот один большой нюанс... писать текст методов в паскале можно только после его полного определения.

Добавлено спустя 3 минуты 7 секунд:
А насчет того, что описание объекта разнесено... можно записывать объект в одном файле... что сейчас, преимущественно и делается.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Зачем два механизма ограничений?

Сообщение sts » 26.10.2015 12:06:50

Лекс Айрин писал(а):А насчет того, что описание объекта разнесено... можно записывать объект в одном файле... что сейчас, преимущественно и делается.


как раз не получается, вынужденно пихают в один юнит.
sts
постоялец
 
Сообщения: 406
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Re: Зачем два механизма ограничений?

Сообщение Дож » 26.10.2015 12:52:12

Мне кажется, что я своим начальным постом ввёл кого-то в заблуждение тем, что там в примерах методы определяются сразу внутри объектов. Приношу свои извинения, тема не об этом, а лишь о разделение объекта на публичную и приватную части.

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

Мотивация

Изначально секция interface задумывалась как секция, в которой описаны только публичные объявления для клиентского кода. К сожалению, с введением ООП сложилась практика программирования, нарушающая эту задумку, т.к. любой публичный объект должен быть полностью объявлен в interface-секции, вместе со всеми приватными составляющими. Хуже того, вслед за объектом часто приходится выносить в интерфейсную часть вспомогательные типы, константы и другие объекты, которые не должны быть видны в клиентском коде.

Решением данной проблемы мог бы являться другой подход к дизайну языка, когда публичная часть объекта объявляется в interface-секции, а приватная — в implementation-секции. Здесь я попытаюсь описать как в текущий синтаксис встроить такую возможность, не ломая совместимость со старым кодом.

Ключевое слово forward

Любые объекты, записи, классы (и, возможно, дженерики) в интерфейсной части можно объявить с пометкой forward:
Код: Выделить всё
type
TMyObject = forward object
  ...
end;


Понимать его следует так, что объект объявлен не полностью, и у него (обязательно) есть продолжение в секции реализации.

Вложенные типы тоже могут быть с пометкой forward, но только если внешний тип имеет пометку forward:
Код: Выделить всё
type
TMyClass = forward class
type
  // Так можно — внешний класс тоже неполный
  TMyObject = forward object
    ...
  end;
  ...
end;

TMyObject = object
type
  // А вот так нельзя — неполный класс внутри полного
  TMyClass = forward class
    ...
  end;
  ...
end;


Ключевое слово нужно по следующей причине. Если бы его не было, то человек, привыкший к текущему паскалю, может по ошибке принять объявление неполного объекта как полного, что введёт его в заблуждение. Пометка forward вносит ясность, говорит что перед нами не полное описание объекта и что-то ещё объявлено в секции реализации.

Возможно, что слово forward является не самым подходящим и корректным. Я его взял из текущей возможности предварительного объявления функций и процедур.

Видимость

Общие правила видимости сохраняются. Объявления выше видны, объявления ниже — нет:
Код: Выделить всё
unit MyUnit;

interface

type
TMyObject = forward object
strict protected
  function Y: LongInt; virtual; abstract;
public
  procedure X;
end;

// Здесь TMyObject.X видно, TMyObject.Y видно только наследникам TMyObject

implementation

// Всё также, ничего не поменялось

type
TMyObject = object
  procedure Z;
protected
  // Эта процедура также составляет интерес: она, в отличии от метода Y,
  // не видна в коде, подключившим этот модуль, но видна в этом модуле ниже
  procedure W; virtual;
end;

// А тут уже видно ещё и Z

procedure TMyObject.X;
begin
  if Y > 0 then begin
    Z;
  end else
    W;
end;

procedure TMuObject.W;
begin
end;

procedure TMyObject.Z;
begin
end;

end.


Исключение составляют свойства. В свойствах можно использовать функции и процедуры, которые будут объявлены в секции реализации:

Код: Выделить всё
unit MyUnit;

interface

type
TMyObject = forward object
  constructor Init;
  property X: LongInt read GetX write SetX;
end;

implementation

const
  SomeConst = 5;

type
TMyObject = object
  FX: LontInt;
  function GetX: LongInt; inline;
  procedure SetX(const Value: LongInt);
end;

constructor TMyObject.Init;
begin
  FX := SomeConst;
end;

function TMyObject.GetX: LongInt;
begin
  Result := FX;
end;

procedure TMyObject.SetX(const Value: LongInt);
begin
  FX := Value;
end;

end.


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

Также концептуально некоторую проблему могут составить операторы, особенно операторы копирования, конструирования и выхода из области видимости (если таковые будут поддержаны в языке), т.к. объявленные только внутри implementation операторы и будут действовать только внутри implementation, и в силу их неявного действия объекты внутри юнита и за его пределами будут неявно вести себя по-разному. Чтобы не столкнуться с проблемами в связи с этим, рекомендуется не описывать операторы в implementation-части объектов.

Лекс Айрин писал(а):
Дож писал(а):Как это нет? Пишется private и данные ограничены.


И вот так. И в С/с++ нет инкапсуляции. Есть модульный доступ к объектам.

При инкапсуляции вообще не должно быть левого доступа к полям объектов. Только через методы. Ну или через свойства, которые суть тоже методы.

И какие же из ныне используемых языков, по Вашему, являются ОО с инкапсуляцией?

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


То, что они туда попадают это неправильная работа оптимизатора. и она, на самом деле, не должна зависить от того виртуальный метод или нет.


Как правильно пишет Mikhail, это фундмаентальная проблема и она непросто решается.
1) Если в модуле A есть класс a, а в модуле B — его наследник b, и где-то в программе используется класс a, то компилятор не может просто так вырезать методы класса b, т.к. знание об их использовании — это некое Realtime-знание.
2) Вызовы виртуальных методов должны производиться через VMT, это медленнее, чем просто вызов функции, и ещё медленнее, чем inline короткой функции.

Дож писал(а):ООП — это не только виртуальные методы, но и удобный, логичный синтаксический сахара. У меня большинство написанных объектов не имеют виртуальных методов.


И вы, при этом, теряете возможность определять потомков с нужными свойствами -- ведь при этом наличие виртуальных методов обязательно.


Все методы, которые нужно переопределять, я делаю виртуальными. Большинство в этом не нуждаются. По коду сразу видно что нужно переопределять, а что для этого не предусмотрено.

Контраргумент, соразмерный аргументу: если все методы виртуальны, и в классе есть некий инвариант, то наследник может его легко нарушить, а нарушение инвариантов — это очень частый источник трудновылавливаемых ошибок.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Зачем два механизма ограничений?

Сообщение Лекс Айрин » 26.10.2015 13:19:53

Дож писал(а):И какие же из ныне используемых языков, по Вашему, являются ОО с инкапсуляцией?


из известных мне.... ни одного. С инкапсуляцией, пожалуй только лисп, возможно, пролог

Дож писал(а):1) Если в модуле A есть класс a, а в модуле B — его наследник b, и где-то в программе используется класс a, то компилятор не может просто так вырезать методы класса b, т.к. знание об их использовании — это некое Realtime-знание.
2) Вызовы виртуальных методов должны производиться через VMT, это медленнее, чем просто вызов функции, и ещё медленнее, чем inline короткой функции.


Вот эти проблемы, для объектов могут решаться на уровне таблиц компилятора. Просто их надо именно решать, а не говорить, что это невозможно. Для любого метода известны условия вызова. Если ни одно из них не выполняется, то метод не нужен. Для ТР, например, постулировалось, что ненужный метод не будет попадать в код. Для Дельфи, почему-то, это уже не так((


Дож писал(а):Большинство в этом не нуждаются.


А может, вы просто не умеете продумывать дерево наследования. Вообще-то базовый класс лучше делать именно с виртуальными методами, а уже в потомках добавлять не виртуальные.

Дож писал(а):Контраргумент, соразмерный аргументу: если все методы виртуальны, и в классе есть некий инвариант, то наследник может его легко нарушить, а нарушение инвариантов — это очень частый источник трудновылавливаемых ошибок.


а зачем добавлять в объекты инварианты? Проще объявить не один, а два/три... 200 дополнительных объектов.А если вы считаете, что инвариант может возникнуть из-за того, что потомок вызвал не так метод предка, то это как раз ошибка программиста, а не компилятора.

По хорошему, и own нужен больше для того чтобы гарантировать, что метод не будет наследоваться. (но его, по идее, можно будет определить заново) Это просто декларация о намерениях программиста.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Зачем два механизма ограничений?

Сообщение Дож » 26.10.2015 15:10:47

Лекс Айрин писал(а):
Дож писал(а):1) Если в модуле A есть класс a, а в модуле B — его наследник b, и где-то в программе используется класс a, то компилятор не может просто так вырезать методы класса b, т.к. знание об их использовании — это некое Realtime-знание.
2) Вызовы виртуальных методов должны производиться через VMT, это медленнее, чем просто вызов функции, и ещё медленнее, чем inline короткой функции.


Вот эти проблемы, для объектов могут решаться на уровне таблиц компилятора. Просто их надо именно решать, а не говорить, что это невозможно. Для любого метода известны условия вызова. Если ни одно из них не выполняется, то метод не нужен. Для ТР, например, постулировалось, что ненужный метод не будет попадать в код. Для Дельфи, почему-то, это уже не так((


Ну давайте рассмотрим пример.
Код: Выделить всё
unit A;

interface

type
PA = ^TA;
TA = object
  constructor Init;
  procedure Some1; virtual;
  procedure Some2; virtual;
end;

var
  Global: PA;

procedure Foo;

implementation

constructor TA.Init;
begin
  Writeln('TA.Init');
end;

procedure TA.Some1;
begin
  Writeln('1');
  Some2;
end;

procedure TA.Some2;
begin
  Writeln('2');
end;

procedure Foo;
begin
  Global^.Some1;
  Global^.Some2;
end;

initialization
  Global := New(PA, Init);
end.


Код: Выделить всё
unit B;

interface

uses
  A;

type
PB = ^TB;
TB = object(TA)
  constructor Init;
  procedure Some1; virtual;
  procedure Some2; virtual;
end;

implementation

constructor TB.Init;
begin
  Writeln('TB.Init');
end;

procedure TB.Some1;
begin
  Writeln('1');
  Some2;
end;

procedure TB.Some2;
begin
  Writeln('2');
  Foo;
end;

end.


Код: Выделить всё
program Test;

uses
  A,
  B;

var
  V: PA;

begin
  V := New(PB, Init);
  V^.Some1;
end.


Я утверждаю, что в этом коде функция Foo и методы Some2 не будут вызваны.

Вот, допустим, есть a.ppu, b.ppu с уже построенным кодом внутри. Объясните мне как компилятор будет анализировать этот код, определять что будет вызвано, а что нет? Что это за таблицы компилятора, что в них будет лежать? Как компилятор будет действовать по шагам? Как поменяется таблица компилятора, если я в конец программы допишу «Global := New(PB, Init);»? Жду подробного описания алгоритма.

Дож писал(а):Большинство в этом не нуждаются.


А может, вы просто не умеете продумывать дерево наследования. Вообще-то базовый класс лучше делать именно с виртуальными методами, а уже в потомках добавлять не виртуальные.


Лучше для кого или для чего? Как именно лучше? Из каких соображений? Зачем мне дерево наследования, для какой задачи?

У меня есть класс TVec2f для вектора, класс TAnsiBuf для буфера в памяти, TTexture2d для хранения двухмерного буфера с текстурой, TJson для хранения распарсенного json-объекта, TDraw — надстройка над OpenGL, TOptions — для удобного парсинга ParamStr/ParamCount. Какие деревья наследования я для них не продумал?

У меня есть класс TStream, у него 4 виртуальных метода и более 20 невиртуальных на них базирующихся. Над TStream есть обёртка TData без виртуальных методов и наследников.

Дож писал(а):Контраргумент, соразмерный аргументу: если все методы виртуальны, и в классе есть некий инвариант, то наследник может его легко нарушить, а нарушение инвариантов — это очень частый источник трудновылавливаемых ошибок.


а зачем добавлять в объекты инварианты?


Это сильный вопрос, очень сильный. Попытаюсь ответить. Если говорить общо, то одно из назначений ООП — гарантировать инварианты в программе. Рассмотрим пример — я написал односвязный список, хранящий набор уникальных значений.
Код: Выделить всё
type
TDojList = object
private
  FNode: PNode;
public
  procedure Insert(P: Pointer);
  function Has(P: Pointer): Boolean;
  procedure Delete(P: Pointer); // удаляет один P
  function GetLastInserted: Pointer; // последнее вставленное значение
end;

...

procedure TDojList.Insert(P: Pointer);
begin
  while Has(P) do
    Delete(P); // не храним дубликаты

  // ... тут вставляем P в конец, чтобы GetLastInserted было корректным
end;

...


Предположим, что все методы виртуальны. Пусть некий условный Лекс Айрин захотел сделать список, в котором гарантируется всегда наличие некого объекта Global. И он решил пойти простым путём, наследованием:
Код: Выделить всё
type
TLexList = object
public
  procedure Delete(P: Pointer);
end;

...

procedure TLexList.Delete(P: Pointer);
begin
  if P <> Global then
    inherited Delete(P);
end;


Тогда код «Lex.Insert(Global);» зависнет. Это не совсем инвариант, но ожидаемое поведение на метод Delete было нарушено, и подобное является проблемой.

Проще объявить не один, а два/три... 200 дополнительных объектов.А если вы считаете, что инвариант может возникнуть из-за того, что потомок вызвал не так метод предка, то это как раз ошибка программиста, а не компилятора.

Тут я вообще не понял о чём речь.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Зачем два механизма ограничений?

Сообщение Mikhail » 26.10.2015 17:22:38

Kemet писал(а):Так они уже созданы - Модула-2, Модула-3, Оберон-2, Активный Оберон...


Устарели, нет смысла их реанимировать... :|
Mikhail
энтузиаст
 
Сообщения: 562
Зарегистрирован: 24.10.2013 16:06:47

Re: Зачем два механизма ограничений?

Сообщение Лекс Айрин » 26.10.2015 17:30:05

Дож писал(а):Ну давайте рассмотрим пример.


Честно, с ходу я этот пример не рассмотрю. Я даже не уверен, что он откомпилируется.

Дож писал(а):Объясните мне как компилятор будет анализировать этот код, определять что будет вызвано, а что нет?


Для каждого объекта создается список методов/ переменных. Для каждого из которых, создается таблицы импорта/экспорта

Прианализе метода заполняется его таблица экспорта(вызываемых этой процедурой методов) По этим таблицам заполняются таблицы импорта.

на уже описанных шагах, по возможности, ссылочные типы преобразуются в обычные. Если не удастся, то и фиг с ними, не так уж и важно.

Если на этом этапе нет ни одного входа, то процедура может быть удалена. То есть, метод не вызывается уж точно.

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

При анализе программы мы ведем себя точно также, но ссылочные типы всегда ассоциируются с реальным текущим типом. В условных конструкциях проверяется возможность достижения веток для каждого использования метода. Если ветка недостижима, то ее не стоит вообще компилировать (Это, кстати делается на этапе оптимизации еще до реальной компиляции)

Так как мы уже знаем, какой метод вызывается по ссылке (мы просто можем для проверки заглянуть какая процедура вызывается/вызвала нас в данный момент)

Так же по таблице экспорта программы мы заполняем таблицу импорта. Если метод не вызывался из самой программы (у него пустой список экспорта), то заполняем его по таблице соответствующей функции.

повторяем оба шага до невозможности заполнения списков экспорта.

А теперь смотрим объекты/методы которых просто нет нет в списке импорта программы и удаляем их.

Дож писал(а):Зачем мне дерево наследования, для какой задачи?


А зачем тогда использовать ООП? Ведь при ООП мы ставим себе задачей поэтапное усложнение объектов, где некий базовый объект (класс) обеспечивает "примитивные рефлексы", а каждый последующий уровень их усложняет.

Дож писал(а):У меня есть класс TVec2f для вектора, класс TAnsiBuf для буфера в памяти, TTexture2d для хранения двухмерного буфера с текстурой, TJson для хранения распарсенного json-объекта, TDraw — надстройка над OpenGL, TOptions — для удобного парсинга ParamStr/ParamCount. Какие деревья наследования я для них не продумал?


Например, можно добавить метаобъект буфер.


Дож писал(а): Если говорить общо, то одно из назначений ООП — гарантировать инварианты в программе.


скорее, гибкость. Которая обеспечивается созданием объектов немного по разному реагирующих на внешние сигналы.

Дож писал(а): Пусть некий условный Лекс Айрин захотел сделать список, в котором гарантируется всегда наличие некого объекта Global. И он решил пойти простым путём, наследованием:


А зачем бы мне стрелять себе в ногу? И потом, если выстрелил, то сам виноват, компилятор лишь может подсказать мне, что это непрактично. Так что именно здесь не язык/компилятор виноват, а я м...к. Не забывайте, что виртуальные методы переписываются мною и обращение к методу предка не является обязательным. При желании, я могу полностью поменять логику работы метода, главное чтобы вызовы были идентичны. Ну и, конечно, что бы он выполнял нужные действия.

Такие вещи есть в каждом языке, некоторые даже используются на практике. Например, в C я встречал использование вечного цикла.


Дож писал(а):Тут я вообще не понял о чём речь.


Возможно, вы пытаетесь создать объект со слишком развитой логикой, которая просто и непринужденно реализуется в нескольких объектах.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Зачем два механизма ограничений?

Сообщение Mikhail » 26.10.2015 17:39:28

А по теме топика скажу так, нынешняя схема с секциями interface и implementation создавалась для процедурно-ориентированной парадигмы и плохо вписывается в ООП. Да и здесь есть проблемы при реализации АТД. По этому лучше вообще отказаться от такой структуры и указывать импорт для каждого элемента отдельно, например так
Код: Выделить всё
public type TMatrix = array of  array of real;

или так, если нужно экспортировать только некоторые описания из секции
Код: Выделить всё
type TPrivateType =
       public TPublicType = record

       end;

т.е. по умолчанию private, а public нужно указывать явно, но private тоже должна возможность указать явно, например так
Код: Выделить всё
public type TRecord = record
           publicfield: TMyType;
           private privatefield: TMyType2;
          end;

Примерно так :roll:
Mikhail
энтузиаст
 
Сообщения: 562
Зарегистрирован: 24.10.2013 16:06:47

Re: Зачем два механизма ограничений?

Сообщение Дож » 26.10.2015 17:46:05

Mikhail, это вариант ответа «Лучше убрать interface и implementation» и у меня есть критика против него: если private и public будут вперемешку по всему модулю, то пользователю модуля потребуется прочесть его целиком, чтобы понять что можно (или нужно) использовать. Это ИМХО ухудшит читаемость кода.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Зачем два механизма ограничений?

Сообщение Mikhail » 26.10.2015 17:57:42

Дож писал(а):Mikhail, это вариант ответа «Лучше убрать interface и implementation» и у меня есть критика против него: если private и public будут вперемешку по всему модулю, то пользователю модуля потребуется прочесть его целиком, чтобы понять что можно (или нужно) использовать.

В общем да, я за то что бы убрать эти секции, но этого нельзя сделать не сломав совместимость, а ради только этого ее ломать не стоит... поэтому я считаю что проще начать с чистого листа.

Дож писал(а):Это ИМХО ухудшит читаемость кода.

С одной стороны да, но разделение описания объекта в разные секции тоже не способствует хорошей читаемости кода.
Но эти проблемы может решить хорошая IDE. :roll:
Mikhail
энтузиаст
 
Сообщения: 562
Зарегистрирован: 24.10.2013 16:06:47

Re: Зачем два механизма ограничений?

Сообщение Kemet » 26.10.2015 18:03:32

Mikhail писал(а):
Kemet писал(а):Так они уже созданы - Модула-2, Модула-3, Оберон-2, Активный Оберон...


Устарели, нет смысла их реанимировать... :|

А зачем их реанимировать? Они живее всех живых.
В каком же месте они для тебя устарели-то?
Kemet
постоялец
 
Сообщения: 241
Зарегистрирован: 10.02.2010 19:28:32
Откуда: Временно оккупированная территория

Re: Зачем два механизма ограничений?

Сообщение Mikhail » 26.10.2015 18:14:52

Kemet писал(а):А зачем их реанимировать? Они живее всех живых.

:D Давай не будем, ладно?

Kemet писал(а):В каком же месте они для тебя устарели-то?


Например в Модуле-2 раздельное (файлы) описание интерфейса и реализации, в Обероне нет обобщенного программирования, Модула-3 комбайн из всего подряд, аля Ада.
Mikhail
энтузиаст
 
Сообщения: 562
Зарегистрирован: 24.10.2013 16:06:47

Re: Зачем два механизма ограничений?

Сообщение Дож » 26.10.2015 18:24:31

Mikhail писал(а):
Дож писал(а):Mikhail, это вариант ответа «Лучше убрать interface и implementation» и у меня есть критика против него: если private и public будут вперемешку по всему модулю, то пользователю модуля потребуется прочесть его целиком, чтобы понять что можно (или нужно) использовать.

В общем да, я за то что бы убрать эти секции, но этого нельзя сделать не сломав совместимость, а ради только этого ее ломать не стоит... поэтому я считаю что проще начать с чистого листа.

Дож писал(а):Это ИМХО ухудшит читаемость кода.

С одной стороны да, но разделение описания объекта в разные секции тоже не способствует хорошей читаемости кода.

Это если у тебя есть только опция «прочесть всё». А если у тебя есть два режима чтения: «прочесть всё» и «прочесть только то, что я мог бы использовать из данного модуля, без технических деталей», то для второго режима interface-секция очень облегчает чтение.

Но эти проблемы может решить хорошая IDE. :roll:

Это плохой аргумент :) Хорошая IDE — не повод подрывать культуру написания хорошего кода!

Добавлено спустя 8 минут 36 секунд:
Лекс Айрин писал(а):

При анализе программы мы ведем себя точно также, но ссылочные типы всегда ассоциируются с реальным текущим типом. В условных конструкциях проверяется возможность достижения веток для каждого использования метода. Если ветка недостижима, то ее не стоит вообще компилировать (Это, кстати делается на этапе оптимизации еще до реальной компиляции)



У меня есть уточняющие вопросы: вот есть, например, функция
Код: Выделить всё
procedure X(I: LongInt);
begin
  if P(I) then begin
    F;
  end else
    G;
end;


Как здесь будет применён анализ достижимости веток? Будет ли компилятор анализировать на каких входах P(I) истинно, или просто посчитает F и G заведомом импортируемыми?
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Зачем два механизма ограничений?

Сообщение Mikhail » 26.10.2015 18:39:59

Дож писал(а):Это если у тебя есть только опция «прочесть всё». А если у тебя есть два режима чтения: «прочесть всё» и «прочесть только то, что я мог бы использовать из данного модуля, без технических деталей», то для второго режима interface-секция очень облегчает чтение.


С одной стороны все правильно, но есть и проблемы усложнение компилятора, усложнение разработки, ИМХО оно того не стоит. Опять же чтение не документированной интерфейсной части мало чего дает все равно надо заглянуть в реализацию, а если есть нормальная документация, то ее и не нужно читать.

Дож писал(а):Это плохой аргумент :) Хорошая IDE — не повод подрывать культуру написания хорошего кода!


Конечно, но не вижу противоречия.
Mikhail
энтузиаст
 
Сообщения: 562
Зарегистрирован: 24.10.2013 16:06:47

Re: Зачем два механизма ограничений?

Сообщение Лекс Айрин » 26.10.2015 18:58:31

Дож писал(а):Как здесь будет применён анализ достижимости веток? Будет ли компилятор анализировать на каких входах P(I) истинно, или просто посчитает F и G заведомом импортируемыми?


Когда я описывал, то считал правильным первый вариант. Так как невозможно понять какая ветка будет правильной не зная условия. Ведь, возможна ситуация, когда функция будет всегда выдавать True/False.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Пред.След.

Вернуться в Компилятор / язык программирования

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

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

Рейтинг@Mail.ru