усиления/деградации ограничений
От: Кодт Россия  
Дата: 15.02.05 11:22
Оценка: +1
Здравствуйте, RailRoadMan, Вы писали:

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


RRM>Если вам по какой-то причине нужен оберон, хорошо, что он есть, мне Оберон не нужен, может пока, может вообще.


RRM>P.S. Просто раздражает, когда Оберон (и иже с ними) выставляют в виде некой панацеи от всего. Но это не к вам.


Я здесь вступлюсь за AVC
Беда языка С++ в том, что очень много опасных преобразований он позволяет делать неявно.
Требуются неслабые усилия, чтобы пресечь эти попытки.

Самое простое: преобразование модели "указатель" в "динамический объект".
void utilize(int* x)
{
  cout << *x << endl;
  delete x;
}

int main()
{
  utilize(new int(7));
  int i = 3;
  utilize(&i);
}

Как видите, где-то в этом коде произошло криминальное изменение семантики — но где именно, в точке delete x или в utilize(&i) ? Знают только авторы кода, да и те после вчерашней пьянки забыли.

Впрочем, средства С++ позволяют разрулить эту ситуацию.
template<class T>
class pointer
{
  T* ptr;
public:
  pointer() : ptr(NULL) {}
  pointer(T* p) : ptr(p) {} // не explicit

  T& operator*() const { return *ptr; }
  T* operator->() const { return ptr; }

  operator pointer<const T>() const { return pointer<const T>(ptr); }
};

template<class T>
class dyn_object : public pointer<T>
{
public:
  dyn_object() {}

private:
  explicit dyn_object(T* p) : pointer(p) {}

  T* get() const { return ptr; }
  friend struct dyn_object_helper;
};

struct dyn_object_helper
{
  template<class T>
  dyn_object<T> do_new() { return dyn_object<T>(new T()); }

  template<class T, class U>
  dyn_object<T> do_new(U u) { return dyn_object<T>(new T(u)); }

  template<class T>
  void do_delete(dyn_object<T> obj) { delete obj.get(); }
};

template<class T>
dyn_object<T> do_new() { return dyn_object_helper::do_new<T>(); }

template<class T, class U>
dyn_object<T> do_new(U u) { return dyn_object_helper::do_new<T>(u); }

template<class T>
void do_delete(dyn_object<T> obj) { dyn_object_helper::do_delete(obj); }


///////////////

void utilize_right(dyn_object<int> obj)
{
  cout << *obj << endl;
  do_delete(obj);
}
void utilize_wrong(pointer<int> ptr)
{
  cout << *ptr << endl;
  do_delete(ptr); // ошибка компиляции
}
void utilize_weak(pointer<int> ptr)
{
  cout << *ptr << endl;
}

int main()
{
  utilize_right(do_new<int>(7));
  utilize_right(new int(7)); // ошибка: нефиг пользоваться голыми указателями

  int i=3;
  utilize_right(&i); // ошибка: откуда я знаю, какой смысл у голого указателя
  utilize_right(pointer<int>(&i)); // ошибка: нехватка полномочий
  utilize_right(dyn_object<int>(&i)); // и опять ошибка: ну нельзя пользоваться голыми указателями!!!

  utilize_weak(new int(7)); // глупо конечно, утечка будет... но это уже нюансы.
  dyn_object<int> obj = do_new<int>(7);
  utilize_weak(obj);
  utilize_weak(&i); // приведение голого указателя к pointer - не криминал (хотя, можно запретить от греха подальше)
}

Здесь уже стало видно, где именно происходит преобразование моделей.

Да, на Обероне нужно гораздо меньше выкручиваться на этот счёт.
Как в С++ весьма мощным средством раздачи по пальцам является накладывание константности, так в Обероне — разделение на статические и динамические объекты.
Впрочем, от кривых рук не спасёт:
TYPE Data = POINTER TO RECORD x: Integer; END;

PROCETUDE touch(VAR p: Data);
BEGIN
  p := NEW Data;
END;

PROCEDURE utilize(VAR p: Data); (* здесь - заявлены неправильные полномочия *)
BEGIN
  Write(p);
  touch(p); (* а с виду и не поймёшь, что переменную изменили... *)
  p.x := 3;
END;

PROCEDURE main();
VAR i,j : POINTER TO Integer;
BEGIN
  i := NEW Data; i.x := 7;
  j := i; (* два указателя на один объект *)
  utilize(j);
  if(i.x <> j.x) Write('приплыли');
END;



17.02.05 11:10: Ветка выделена из темы Нужна ли Оберон-ОС защита памяти?
Автор: AVC
Дата: 19.01.05
— AndrewVK
Перекуём баги на фичи!
Re[24]: усиления/деградации ограничений
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.02.05 11:53
Оценка: +2
Здравствуйте, Кодт, Вы писали:


К>PROCEDURE utilize(VAR p: Data); (* здесь — заявлены неправильные полномочия *)

К>BEGIN
К> Write(p);
К> touch(p); (* а с виду и не поймёшь, что переменную изменили... *)
К> p.x := 3;
К>END;

К>PROCEDURE main();

К>VAR i,j : POINTER TO Integer;
К>BEGIN
К> i := NEW Data; i.x := 7;
К> j := i; (* два указателя на один объект *)
К> utilize(j);
К> if(i.x <> j.x) Write('приплыли');
К>END;
К>[/pascal]

В Net эта проблема решается через явное указание ref или out в вызываемых методах.

PROCEDURE utilize(VAR p: Data); (* здесь — заявлены неправильные полномочия *)
BEGIN
Write(p);
touch(var p); (* а с виду и не поймёшь, что переменную изменили... *)
p.x := 3;
END;

PROCEDURE main();
VAR i,j : POINTER TO Integer;
BEGIN
i := NEW Data; i.x := 7;
j := i; (* два указателя на один объект *)
utilize(var j);
if(i.x <> j.x) Write('приплыли');
END;
К>[/pascal]
Многие в Net положительно отнеслись к такому синтаксису (как и я). Особенно когда не знаешь всех методов и такого рода ошибки уменьшаются и читабельность увеличивается.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
и солнце б утром не вставало, когда бы не было меня
Re[24]: усиления/деградации ограничений
От: AVC Россия  
Дата: 15.02.05 12:05
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Да, на Обероне нужно гораздо меньше выкручиваться на этот счёт.

К>Как в С++ весьма мощным средством раздачи по пальцам является накладывание константности, так в Обероне — разделение на статические и динамические объекты.
К>Впрочем, от кривых рук не спасёт:
К>
К>TYPE Data = POINTER TO RECORD x: Integer; END;

К>PROCETUDE touch(VAR p: Data);
К>BEGIN
К>  p := NEW Data;
К>END;

К>PROCEDURE utilize(VAR p: Data); (* здесь - заявлены неправильные полномочия *)
К>BEGIN
К>  Write(p);
К>  touch(p); (* а с виду и не поймёшь, что переменную изменили... *)
К>  p.x := 3;
К>END;

К>PROCEDURE main();
К>VAR i,j : POINTER TO Integer;
К>BEGIN
К>  i := NEW Data; i.x := 7;
К>  j := i; (* два указателя на один объект *)
К>  utilize(j);
К>  if(i.x <> j.x) Write('приплыли');
К>END;
К>


А куда, собственно, приплыли?
Ошибки вроде не случилось.
Если бы процедура utilize не предполагала возможности изменения указателя, то там бы не стоял квалификатор VAR. А т.к. VAR стоит, то компилятор в курсе. Если потребуется, "сгенерит" необходимую проверку.
Есть более трудные ситуации (например, смена динамического типа указателя в теле type guard WITH), но и они в Обероне пристойно "разруливаются".
Цитирую Oakwood guidelines:

2.4 WITH and guarded variables
It is possible to alter a guarded pointer variable within the scope of a guarding WITH
statement, example:
TYPE
T = RECORD END; P = POINTER TO T;
T1 = RECORD (T) END; P1 = POINTER TO T1;
T2 = RECORD (T) END; P2 = POINTER TO T2;
PROCEDURE X;
VAR p: P; p1: P1; p2: P2;
PROCEDURE Y;
BEGIN
The Oakwood Guidelines for Oberon-2 Compiler DevelopersOctober 20, 1995 10
p := p2
END Y;
BEGIN
NEW (p); NEW(p1); NEW(p2); p := p1;
WITH p: P1 DO
Y (*p is now of type P2 and not P1*)
END
END X;
A practical way to handle this is :
If the compiler can be sure it is safe then give no warning message. If there can be any
doubt then do give a warning message. A sophisticated compiler could automatically
insert the additional relevant type guard checks.

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[25]: усиления/деградации ограничений
От: Кодт Россия  
Дата: 15.02.05 12:13
Оценка:
Здравствуйте, AVC, Вы писали:

AVC>А куда, собственно, приплыли?

AVC>Ошибки вроде не случилось.
AVC>Если бы процедура utilize не предполагала возможности изменения указателя, то там бы не стоял квалификатор VAR. А т.к. VAR стоит, то компилятор в курсе. Если потребуется, "сгенерит" необходимую проверку.

Компилятор-то в курсе, да у программиста руки были кривые и глаза косые.
Ведь можно сказать, что компилятор С/С++ тоже в курсе, и раз написали "указатель", то и надругаться над ним можем во всём спектре (в том числе — адресная арифметика и менеджмент памяти), а не только в том, которое было задумано.
Перекуём баги на фичи!
Re[25]: усиления/деградации ограничений
От: Кодт Россия  
Дата: 15.02.05 12:20
Оценка: +1
Здравствуйте, Serginio1, Вы писали:

S> В Net эта проблема решается через явное указание ref или out в вызываемых методах.

S> Многие в Net положительно отнеслись к такому синтаксису (как и я). Особенно когда не знаешь всех методов и такого рода ошибки уменьшаются и читабельность увеличивается.

Я такое делаю в С++ при передаче out и inout параметров в COM-овские методы.
Заодно решается вопрос о приведении типов.
Перекуём баги на фичи!
Re[26]: усиления/деградации ограничений
От: AVC Россия  
Дата: 15.02.05 12:51
Оценка:
Здравствуйте, Кодт, Вы писали:

AVC>>А куда, собственно, приплыли?

AVC>>Ошибки вроде не случилось.
AVC>>Если бы процедура utilize не предполагала возможности изменения указателя, то там бы не стоял квалификатор VAR. А т.к. VAR стоит, то компилятор в курсе. Если потребуется, "сгенерит" необходимую проверку.
К>Компилятор-то в курсе, да у программиста руки были кривые и глаза косые.
К>Ведь можно сказать, что компилятор С/С++ тоже в курсе, и раз написали "указатель", то и надругаться над ним можем во всём спектре (в том числе — адресная арифметика и менеджмент памяти), а не только в том, которое было задумано.

Я так и не понял, в чем именно ошибка.
Ваш код примерно соответствует следующему:
typedef struct { int x; } *Data;
void main()
{
    Data *p, *q;
    p = malloc(sizeof *p);
    p->x = 7;
    q = p; /* два указателя на один объект */
    q = malloc(sizeof *q); /* уже нет */
    q->x = 3;
    if (p->x != q->x)
        printf("приехали"); /* здесь Вы кричите "пожар!" А в чем собственно дело? */
}

Я вообще не вижу ошибки. (Код, конечно, странный. Но ведь неизвестно, для чего он.)
Вообще, человек и компилятор отвечают каждый за свой участок.
Человек за осмысленность и смысловую корректность вычислений.
Компилятор — за безопасность системы типов.
Вам не удалось (по крайней мере, в данном случае) обмануть компилятор Оберона.
Так что ничего общего с "глюкавостью" Си++ здесь нет.

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[27]: усиления/деградации ограничений
От: AVC Россия  
Дата: 15.02.05 13:20
Оценка:
Здравствуйте, AVC, Вы писали:

AVC>
Data *p, *q;

Конечно, правильно было бы
Data p, q;
Просто сказалась привычка объявлять указатели явно (со звездочкой).

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[27]: усиления/деградации ограничений
От: Кодт Россия  
Дата: 15.02.05 13:55
Оценка:
Здравствуйте, AVC, Вы писали:

AVC>Я так и не понял, в чем именно ошибка.


Ошибка
— локально, в неправильном использовании прав доступа
— если смотреть шире, в слишком мягкой политике языка

AVC>Я вообще не вижу ошибки. (Код, конечно, странный. Но ведь неизвестно, для чего он.)

AVC>Вообще, человек и компилятор отвечают каждый за свой участок.
AVC>Человек за осмысленность и смысловую корректность вычислений.
AVC>Компилятор — за безопасность системы типов.

То есть, ты считаешь, что право С++ удалять указатель — это криминал, а право Оберона ковырять объект, доступный по неконстантной ссылке или по указателю — это программист сам дурак. А почему не наоборот?

AVC>Вам не удалось (по крайней мере, в данном случае) обмануть компилятор Оберона.

AVC>Так что ничего общего с "глюкавостью" Си++ здесь нет.

А вот здесь я как апологет С++ скажу, что Оберон отдыхает в сторонке!
С помощью шаблонов можно очень тонко регулировать права использования разделяемых данных (включая параметры, передаваемые в и из функции).
Правда, "строгость законов компенсируется необязательностью их исполнения", то есть требует от программистов соглашения по кодированию. Например, не использовать голые указатели.
Практический пример — ATL. Никто не мешает забить на CComPtr и пользоваться голым IXxxx*, мучительно вспоминая, сколько раз ты сделал AddRef... но очень быстро привыкаешь к хорошему
Перекуём баги на фичи!
Re[28]: усиления/деградации ограничений
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.02.05 14:21
Оценка:
Здравствуйте, Кодт, Вы писали:


К>А вот здесь я как апологет С++ скажу, что Оберон отдыхает в сторонке!

К>С помощью шаблонов можно очень тонко регулировать права использования разделяемых данных (включая параметры, передаваемые в и из функции).
Если смотреть на Net, то там полное торжество идей Вирта. Дженерики появятся и в Обероне.Net.
Интерес оберона в том, что уже есть операционка на нем. Лонгхорн выйдет еще не скоро , да и натива в нем будет немало.
Как уже говорил для существует Compact фреймворк итд. Для определенного круга задач не требуются глобальные ОСи.
А по конкретные задачи вполне может подойти и оберон системы. Все таки они живут и развиваются.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
и солнце б утром не вставало, когда бы не было меня
Re[28]: усиления/деградации ограничений
От: AVC Россия  
Дата: 15.02.05 14:39
Оценка:
Здравствуйте, Кодт, Вы писали:

AVC>>Я так и не понял, в чем именно ошибка.

К>Ошибка
К>- локально, в неправильном использовании прав доступа
К>- если смотреть шире, в слишком мягкой политике языка

Я и сейчас не вижу ошибки.
Так как Вы говорите о неправильном использовании прав доступа, то где-то должно существовать правильное использование.
Предлагаю сделать так. Вы пишете правильный вариант. (Можно на Си++. Я прощу. )
А я таким путем проникну в суть вещей.

AVC>>Я вообще не вижу ошибки. (Код, конечно, странный. Но ведь неизвестно, для чего он.)

AVC>>Вообще, человек и компилятор отвечают каждый за свой участок.
AVC>>Человек за осмысленность и смысловую корректность вычислений.
AVC>>Компилятор — за безопасность системы типов.
К>То есть, ты считаешь, что право С++ удалять указатель — это криминал, а право Оберона ковырять объект, доступный по неконстантной ссылке или по указателю — это программист сам дурак. А почему не наоборот?

Я что-то не понимаю.
Вы сами написали utilize(VAR p: Data). Если бы не хотели позволить модификацию p, написали бы utilize(p: Data), и дело с концом.

AVC>>Вам не удалось (по крайней мере, в данном случае) обмануть компилятор Оберона.

AVC>>Так что ничего общего с "глюкавостью" Си++ здесь нет.

К>А вот здесь я как апологет С++ скажу, что Оберон отдыхает в сторонке!

К>С помощью шаблонов можно очень тонко регулировать права использования разделяемых данных (включая параметры, передаваемые в и из функции).

Например, в компонентном Паскале кроме VAR есть спецификаторы IN и OUT.
И не нужно быть гуру обобщенного программирования.
При принятии Oakwood guidelines обсуждался вопрос о параметрах только для чтения (VAR p-: Data), но был отклонен (на вполне разумных основаниях).

К>Правда, "строгость законов компенсируется необязательностью их исполнения", то есть требует от программистов соглашения по кодированию. Например, не использовать голые указатели.

К>Практический пример — ATL. Никто не мешает забить на CComPtr и пользоваться голым IXxxx*, мучительно вспоминая, сколько раз ты сделал AddRef... но очень быстро привыкаешь к хорошему

А вот это и есть суровая правда жизни.
На всякую конвенцию найдется свой Паниковский.

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[29]: усиления/деградации ограничений
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.02.05 14:59
Оценка:
Здравствуйте, AVC, Вы писали:

A
AVC>Я что-то не понимаю.
AVC>Вы сами написали utilize(VAR p: Data). Если бы не хотели позволить модификацию p, написали бы utilize(p: Data), и дело с концом.

В Net из за перегрузки методов может существовать
utilize(VAR p: Data)
и
utilize(p: Data)

Поэтому первый метод ты обязан вызвать как
utilize(VAR p)

Многие по этому поводу возмущались. Но мне лично вызов с явным указанием нравится больше, даже в языках не поддерживающие перегрузку методов. Все сразу видно не вникая в объявление метода
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
и солнце б утром не вставало, когда бы не было меня
Re[30]: усиления/деградации ограничений
От: AVC Россия  
Дата: 15.02.05 15:25
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> В Net из за перегрузки методов может существовать

S> utilize(VAR p: Data)
S> и
S> utilize(p: Data)
S> Поэтому первый метод ты обязан вызвать как
S> utilize(VAR p)
S> Многие по этому поводу возмущались. Но мне лично вызов с явным указанием нравится больше, даже в языках не поддерживающие перегрузку методов. Все сразу видно не вникая в объявление метода

Спасибо.
Это мне пока понятнее, чем пример, приведенный Кодтом в качестве критики.
Думаю, что внесение ясности в код стоит того, чтобы написать лишний раз VAR.
Но "критический запал" Кодта остается мне непонятным (в данном случае).
Ведь в Обероне нет перегрузки методов, позволяющей применять VAR произвольно.

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[29]: усиления/деградации ограничений
От: Кодт Россия  
Дата: 15.02.05 15:39
Оценка: 15 (2)
Здравствуйте, AVC, Вы писали:

AVC>>>Я так и не понял, в чем именно ошибка.

К>>Ошибка
К>>- локально, в неправильном использовании прав доступа
К>>- если смотреть шире, в слишком мягкой политике языка

AVC>Я и сейчас не вижу ошибки.


Ошибка логическая, компилятором не просекаемая.
Она стоит в одном ряду с
const double PI = exp(1.0);

Точнее, как раз её-то просечь можно.

AVC>Так как Вы говорите о неправильном использовании прав доступа, то где-то должно существовать правильное использование.

AVC>Предлагаю сделать так. Вы пишете правильный вариант. (Можно на Си++. Я прощу. )
AVC>А я таким путем проникну в суть вещей.

Ну я уже писал выше — dyn_object<T>, pointer<T>

AVC>>>Я вообще не вижу ошибки. (Код, конечно, странный. Но ведь неизвестно, для чего он.)

AVC>>>Вообще, человек и компилятор отвечают каждый за свой участок.
AVC>>>Человек за осмысленность и смысловую корректность вычислений.
AVC>>>Компилятор — за безопасность системы типов.
К>>То есть, ты считаешь, что право С++ удалять указатель — это криминал, а право Оберона ковырять объект, доступный по неконстантной ссылке или по указателю — это программист сам дурак. А почему не наоборот?

AVC>Я что-то не понимаю.

AVC>Вы сами написали utilize(VAR p: Data). Если бы не хотели позволить модификацию p, написали бы utilize(p: Data), и дело с концом.

Не с концом. Давай введём ещё один уровень опосредования
TYPE Foo = POINTER TO RECORD x:Integer; END;
     Bar = POINTER TO RECORD f:Foo;     END;

PROCEDURE deface(b:Bar); (* казалось бы, константа... *)
BEGIN
  b.f := NEW Foo; (* но объект поменять - как нефиг делать *)
  b.f.x := 456;
END;

PROCEDURE main();
VAR a,b:Foo;
    c:Bar;
BEGIN
  a := NEW Foo;
  a.x := 123;
  c := NEW Bar;
  c.f := a;
  deface(c);
  b := c.f;
  if(a.x <> b.x) Write("приплыли");
END;


AVC>>>Вам не удалось (по крайней мере, в данном случае) обмануть компилятор Оберона.

AVC>>>Так что ничего общего с "глюкавостью" Си++ здесь нет.

К>>А вот здесь я как апологет С++ скажу, что Оберон отдыхает в сторонке!

К>>С помощью шаблонов можно очень тонко регулировать права использования разделяемых данных (включая параметры, передаваемые в и из функции).

AVC>Например, в компонентном Паскале кроме VAR есть спецификаторы IN и OUT.

AVC>И не нужно быть гуру обобщенного программирования.
AVC>При принятии Oakwood guidelines обсуждался вопрос о параметрах только для чтения (VAR p-: Data), но был отклонен (на вполне разумных основаниях).

Кстати, с константностью есть ещё один момент — а именно, глубина распространения константности.
Объект, доступный по константному указателю (например, члену константного объекта) — константный или нет?
С++ считает, что нет, хотя в ряде случаев это может явиться источником ошибок. А в другом ряде случаев — это не ошибка.
Lint такие вещи старается находить и предупреждать.

Что здесь можно сделать? Ввести два типа указателей, с распространением константности и без распространения.
Опять же, средствами С++,
template<class T>
class constable_pointer
{
  T* ptr;
public:
  /* тут всякие конструкторы, присваивания и т.п. */

  T       * operator->()       { return ptr; }
  T const * operator->() const { return ptr; }

  T       & operator*()       { return *ptr; }
  T const & operator*() const { return *ptr; }

  operator T       * () const { return ptr; }
  operator T const * () const { return ptr; }
};

struct Foo { int x; };

struct Bar1 { Foo* f; }; // добрый указатель
struct Bar2 { constable_pointer<Foo> f; }; // злой указатель

void deface(const Bar1& b1, const Bar2& b2)
{
  b1.f->x = 456;
  b2.f->x = 456; // ошибочка вышла!
}


Кто-то может сказать — ну и изврат же это! Вместо T* писать constable_pointer<T>, dyn_object<T> и т.п.
Но ведь это не сильно длиннее Паскаля, ПЛ, Оберона — POINTER TO T.



Я сейчас фонтанирую идеями насчёт системы шаблонов. Пока что были озвучены
— права на delete/delete[],
— права на адресную арифметику (от которой, впрочем, можно и совсем отказаться),
— транзитивность константности (и, кстати, volatile...)
Ещё вспомним про разнообразные политики владения (монопольное, разделяемое, эстафетное как у auto_ptr)...

Нашёлся бы кто-то, кто приведёт все эти фичи в систему (а может быть, даже и я — как раз сейчас новый проект стартует, там постараемся сделать по-человечески).
Перекуём баги на фичи!
Re[31]: усиления/деградации ограничений
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.02.05 15:43
Оценка:
Здравствуйте, AVC, Вы писали:

AVC>Но "критический запал" Кодта остается мне непонятным (в данном случае).

AVC>Ведь в Обероне нет перегрузки методов, позволяющей применять VAR произвольно.

Наверное главное в этом
touch(p); (* а с виду и не поймёшь, что переменную изменили... *)

хотя можно былобы и так

touch({* var *} p); (не знаю какие комментарии в обероне)
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
и солнце б утром не вставало, когда бы не было меня
Re[31]: усиления/деградации ограничений
От: Кодт Россия  
Дата: 15.02.05 15:50
Оценка: +1
Здравствуйте, AVC, Вы писали:

AVC>Но "критический запал" Кодта остается мне непонятным (в данном случае).

AVC>Ведь в Обероне нет перегрузки методов, позволяющей применять VAR произвольно.

Я не на Оберон нападаю! Я почувствовал запах дичи касающейся программирования вообще.
И в С++, и в Обероне есть одинаковые проблемы, просто в С++ дырка пошире, зато и заплатки навесить попроще
Если уж на кого катить бочку, так это на старый добрый Фортран. Вот там — веселье с константностью!

Впрочем, у всех этих изысков есть оборотная сторона: количество legacy code.
Например, в моей компании — исходников порядка сотен мегабайт, если не гигабайт. Починить их все — нереально. Поэтому, если придётся скрещивать новый, красивый, безопасный код со старым — то возникнут разнообразные проблемы (конечно, решаемые, но вряд ли решаемые тривиально).

У Оберона с этим, наверное, проще. Во-первых, меньше кода написано, во-вторых, часть проблем была на корню пресечена.
Перекуём баги на фичи!
Re[32]: усиления/деградации ограничений
От: AVC Россия  
Дата: 15.02.05 15:55
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Наверное главное в этом

S> touch(p); (* а с виду и не поймёшь, что переменную изменили... *)
S> хотя можно былобы и так
S> touch({* var *} p); (не знаю какие комментарии в обероне)

Комментарии в Обероне — круглые скобки со звездочками: (* комментарий *).
Комментарии могут быть вложенными.
Кодт только что прислал большой пост; может быть сейчас все прояснится.

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[33]: усиления/деградации ограничений
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.02.05 16:08
Оценка:
Здравствуйте, AVC, Вы писали:



AVC>Комментарии в Обероне — круглые скобки со звездочками: (* комментарий *).

Эх а ведь хотел круглые скобочки (просто в Delphi и те и те катят.
На самом деле по const например для Delphi существуют ограничения, да и const там для объектов поддерживающих подсчет ссылок

      TProba = class
   I:Integer;
   Procedure ConstMethod(Const A:Tproba);
   Procedure NotConstMethod(Const A:Tproba); 
  end;
    
    procedure TForm1.Button1Click(Sender: TObject);
var A: Tproba;
begin
    A:=TProba.Create;
    A.ConstMethod(a);
end;

{ TProba }

procedure TProba.ConstMethod(const A: Tproba);
begin
 A:=TProba.Create; // не прокатывает
 A.I:=3; // прокатывает
 NotConstMethod(A); // прокатывает 
end;

procedure TProba.NotConstMethod(const A: Tproba);
begin
 A.I:=3;
end;


А как с этим в обероне. Кстати в Net отказались от Const наверное по причине отсутствия подсчета ссылок и трудности предотвращения изменений как вызоа NotConstMethod из ConstMethod
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
и солнце б утром не вставало, когда бы не было меня
Re[30]: усиления/деградации ограничений
От: AVC Россия  
Дата: 15.02.05 16:52
Оценка: 1 (1)
Здравствуйте, Кодт, Вы писали:

AVC>>Я что-то не понимаю.

AVC>>Вы сами написали utilize(VAR p: Data). Если бы не хотели позволить модификацию p, написали бы utilize(p: Data), и дело с концом.
К>Не с концом. Давай введём ещё один уровень опосредования
К>
К>TYPE Foo = POINTER TO RECORD x:Integer; END;
К>     Bar = POINTER TO RECORD f:Foo;     END;

К>PROCEDURE deface(b:Bar); (* казалось бы, константа... *)
К>BEGIN
К>  b.f := NEW Foo; (* но объект поменять - как нефиг делать *)
К>  b.f.x := 456;
К>END;

К>PROCEDURE main();
К>VAR a,b:Foo;
К>    c:Bar;
К>BEGIN
К>  a := NEW Foo;
К>  a.x := 123;
К>  c := NEW Bar;
К>  c.f := a;
К>  deface(c);
К>  b := c.f;
К>  if(a.x <> b.x) Write("приплыли");
К>END;
К>


Так. Начинаю видеть проблему.
Вот почему мне нужна (разумная) критика.
Отвечаю пока кратко.
Проблему признаю. Но, кажется, в Обероне она решается просто.
Беру компилятор XDS. (Наверное, в руки? )
Он позволяет применять (по требованию) спецификатор - (read-only) для параметров-значений.
Вот пример кода. (Прошу прощения за его "аляповатость".)
<*+MAIN*>
<*+O2EXTENSIONS*> (* разрешаю использовать (в частности) readonly параметры *)
MODULE O2Ext;

IMPORT Out;

TYPE
    IPtr = POINTER TO RECORD x: INTEGER END;
    PPtr = POINTER TO PRec;
    PRec = RECORD p: IPtr END;
    
VAR
    p: IPtr;
    q: PPtr;

PROCEDURE test(q-: PRec);
VAR p: IPtr;
BEGIN
    NEW(p); p.x := 2;
    q.p := p; (* эту строку не пропускает компилятор *)
END test;
    
BEGIN
    NEW(p); p.x := 1;
    NEW(q); q.p := p;
    test(q^);
    IF q.p.x # p.x THEN Out.String("Oops!"); END;
END O2Ext.

Компилятор не допускает изменения параметра для чтения.

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[34]: усиления/деградации ограничений
От: AVC Россия  
Дата: 15.02.05 17:12
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> А как с этим в обероне. Кстати в Net отказались от Const наверное по причине отсутствия подсчета ссылок и трудности предотвращения изменений как вызоа NotConstMethod из ConstMethod


(следует читать с большой важностью ) Как коренной Си++янин не в курсе тонкостей каких-то там Delphi.
(Просто так получилось. На объектном Турбо-паскале писал в начале 90-х.)
Создается впечатление, что class в Delphi изначально ссылочный тип (я прав?), а модификатор const относится только к самому указателю.
В Обероне есть возможность передавать записи по значению. (Это не значит, что они обязательно копируются в стек. Просто гарантируется, что исходная запись не изменится.)
На самом деле, даже расширение "-" не обязательно.

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[31]: усиления/деградации ограничений
От: AVC Россия  
Дата: 15.02.05 17:20
Оценка: 5 (1)
Здравствуйте, AVC, Вы писали:

На самом деле, использование расширения необязательно.
Вот немного модифицированный предыдущий пример.
<*+MAIN*>
MODULE O2Ext;

IMPORT Out;

TYPE
    IPtr = POINTER TO RECORD x: INTEGER END;
    PPtr = POINTER TO PRec;
    PRec = RECORD p: IPtr END;
    
VAR
    p: IPtr;
    q: PPtr;

PROCEDURE test(q: PRec);
VAR p: IPtr;
BEGIN
    NEW(p); p.x := 2;
    q.p := p;
END test;
    
BEGIN
    NEW(p); p.x := 1;
    NEW(q); q.p := p;
    test(q^);
    IF q.p.x # p.x THEN
        Out.String("Oops!");
    ELSE
        Out.String("Oberon forever!");
    END;
END O2Ext.
Теперь он проходит компиляцию, но печатает, конечно, Oberon forever!

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.