OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Вторник, 11 Август, 2020 13:54

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 154 ]  На страницу Пред.  1, 2, 3, 4, 5, 6, 7, 8  След.
Автор Сообщение
СообщениеДобавлено: Пятница, 30 Январь, 2009 17:13 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2180
Откуда: Нижний Новгород
Александр Ильин писал(а):
Если уж не доки, то читайте хотя бы форум, Алексей.

Так ткните носом в доку, прочитаю. Пролистал Component Pascal Language Report, упоминания не нашел.

PS. Нашел вот это:
Цитата:
All fields or elements of a newly allocated record or array are cleared, which implies that all
embedded pointers and procedure variables are initialized to NIL.

Но, насколько я понял, тут first & last не принадлежат какой-либо записи или массиву, они на уровне модуля.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 17:40 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2180
Откуда: Нижний Новгород
Сергей Губанов писал(а):
Alexey Veselovsky писал(а):
магический элемент empty. Эдакий типизированный нуль.

Зачем?


Как минимум лучшая читаемость. empty это допустимое значение. nil -- значит что-то пошло не так (например не удалось память выделить). empty -- в пространстве нормального течения программы, nil -- системная ошибка.

Как-то так.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 17:41 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2349
Откуда: Россия, Томск
Alexey Veselovsky писал(а):
Так ткните носом в доку, прочитаю. Пролистал Component Pascal Language Report, упоминания не нашел.

Но, насколько я понял, тут first & last не принадлежат какой-либо записи или массиву, они на уровне модуля.
Вас конкретно на уровне модуля интересует - пожалуйста:
Component Pascal Language Report - 11. Modules писал(а):
Variables declared in a module are cleared prior to the execution of the module body. This implies that all pointer or procedure typed variables are initialized to NIL.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 17:49 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2180
Откуда: Нижний Новгород
Спасибо. С этим случаем разобрался.
Чтобы окончательно небыло путаницы -- есть ли в CP случаи когда ссылки не будут умолчательно инициироваться nil'ом?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 17:57 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2349
Откуда: Россия, Томск
Alexey Veselovsky писал(а):
Чтобы окончательно небыло путаницы -- есть ли в CP случаи когда ссылки не будут умолчательно инициироваться nil'ом?
Нет таких случаев в этом языке.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 18:00 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2349
Откуда: Россия, Томск
Сергей Губанов писал(а):
Зачем?
Я чего-то не понимаю, чего тут многие не понимают. Может быть, это я не так понимаю, и мне только кажется, что я понял. А кажется мне вот что: иногда NIL нужен, иногда - мешает. Тут было много длинных слов сказано, а мы консерваториев не кончали, поэтому постараюсь попроще изложить.

По сути NIL - это константа универсального типа, совместимая по присваиванию с любым указателем. Универсальность её оборачивается проблемой, особенно в тех задачах, где NIL по семантике не нужен, а реализация требует указателей (ибо куда без них?). Предлагается отказаться от NIL, а максимально своевременную инициализацию указателей проконтролировать уже на этапе компиляции. Как это реализовать - вопрос десятый. Например, заставить вместо NEW писать специализированные процедуры-конструкторы, и следить, чтобы в них было присвоение для каждого поля-указателя создаваемого объекта. Другой вариант - каким-то образом отслеживать факт неинициализированности значения и выдавать ошибку при доступе по указателю - опять же, на этапе компиляции, примерно так, как компилятор может предупреждать об использовании значения неинициализированной локальной переменной. Не важно, как именно реализовать, но идея - такая.

Соответственно, те задачи, в которых NIL не требуется, смогут быть уверены, что NIL у них не встретится. А те задачи, где NIL нужен - им сам Бог велел завести себе типизированную константу с аналогичным смыслом. Например, так:
Код:
MODULE Lists;

IMPORT Log;

TYPE
   List* = POINTER TO ABSTRACT RECORD
      next*: List
   END;

   Nil = POINTER TO RECORD (List)
   END;

VAR nil-: List;

PROCEDURE (lst: List) Do- (), NEW;
BEGIN
END Do;

PROCEDURE (lst: Nil) Do ();
BEGIN
   Log.String ("Lists.nil.Do() attempt!"); Log.Ln;
   (* HALT (100); -- по вкусу! -- *)
END Do;

PROCEDURE Init;
VAR tmp: Nil;
BEGIN
   NEW (tmp);
   nil := tmp;
END Init;

BEGIN Init;
END Lists.
Дальнейшая работа - как описано в посте выше. Вместо
WHILE list.next # NIL DO ...
пишем
WHILE list.next # Lists.nil DO ...

Преимущества: присвоить беcтиповый NIL указателю next компилятор не даст, позволит только создать копию значения Lists.nil (или любой другой переменной подходящего типа, которая тоже не может быть = NIL). Соответственно, в случае плохого кода мы получим не гарантированную смерть, а предусмотренный механизм обработки. Ожидается, что большая часть - фатальных! - ошибок отфильтруется на этапе компиляции, а в рантайме останутся только такие, когда по ошибке передан не тот объект или не в ту процедуру.

Я правильно понимаю суть обсуждения?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 18:22 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
>> ...на этапе компиляции. Как это реализовать - вопрос десятый.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 20:35 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Сергей Губанов писал(а):
А можно на примере узнать как "отменяются" нулевые ссылки?

Легко :)

Код:
  VAR
    first, last: Item;


Один глобальный список? Ну-ну ;) Ладно, переписываем вот так:

Код:
  VAR
    first, last: OPTIONAL Item;


Дальше:

Код:
  PROCEDURE Put* (value: INTEGER);
    VAR item: Item;
  BEGIN NEW(item); item.value := value;
    IF last # NIL THEN last.next := item ELSE first := item END;
    last := item
  END Put;


Переписываем без NIL:

Код:
  PROCEDURE Put* (value: INTEGER);
    VAR item: Item;
  BEGIN
    NEW(item);
   
    WITH
        first: Item DO
            item.next := first;
            WITH last: Item DO last.next = item
            ELSE HALT(-1)
            END
        ELSE
            item.next := item;
            first := item
    END

    last := item
  END Put;


Принципиальный момент: компилятор должен ругнуться, если item.next остался непроиничен.

Дальше:

Код:
  PROCEDURE Get* (OUT value: INTEGER; OUT ok: BOOLEAN);
  BEGIN
    IF first # NIL THEN
      value := first.value; ok := TRUE; first := first.next;
      IF first = NIL THEN last := NIL END
    ELSE
      value := 0; ok := FALSE
    END
  END Get;


Переписываем без NIL:

Код:
  PROCEDURE Get* (OUT value: INTEGER; OUT ok: BOOLEAN);
  BEGIN
    WITH first: Item DO
      value := first.value;
      ok := TRUE;
      IF first # first.next THEN
          first := first.next
      ELSE
          first := NIL;
          last := NIL
      END
    ELSE
      value := 0;
      ok := FALSE
    END
  END Get;


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 20:44 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Сергей Губанов писал(а):
Компилятор этого не может сделать.


Гы :) Современные компиляторы даже C++ могут компилить ;) Так что такую фигню как проверить инициализацию всех ссылок - вообще без проблем реализовать.

Сергей Губанов писал(а):
Поэтому, вопрос первый: как надо изменить язык, чтобы компилятор мог?


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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 20:47 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Александр Ильин писал(а):
Я правильно понимаю суть обсуждения?


Да. Только всегда заводить типизированную константу запарно. Поэтому я предлагаю OTIONAL и явное приведение типа.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 21:08 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9271
Откуда: Россия, Орёл
Да, предложение любопытное. О подобном думал и сам когда-то по случаю.
Только когда Вы начинаете с "отменим NIL", то непонятно, что имеется в виду.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 21:42 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2349
Откуда: Россия, Томск
Vlad, у меня что-то в голове не состыковалось:
Vlad писал(а):
Переписываем без NIL:
Код:
...
      ELSE
          first := NIL;
          last := NIL
      END
...
Всё-таки NIL нужен оказался?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 21:54 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Александр Ильин писал(а):
Vlad, у меня что-то в голове не состыковалось:


NIL можно присвоить только OPTIONAL типам. Просто ссылке нельзя присвоить NIL.
Код:
VAR item1: OPTIONAL Item,
      item2: Item;
 ...
     item1 := NIL; (* OK *)
     item2 := NIL; (* ошибка компиляции *)
...
    item1.filed := 3; (* ошибка компиляции *)
    item2.filed := 3; (* OK *)
    WITH item1: Item DO item1.field := 3; (* OK *)
...
    item1 := item2; (* OK *)
    item2 := item1; (* ошибка компиляции *)
    WITH item1: Item DO item2 := item1; (* OK *)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 22:08 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Всё это нагромождение имело бы смысл если бы компилятор мог гарантировать проверку, но...
Vlad писал(а):
Так что такую фигню как проверить инициализацию всех ссылок - вообще без проблем реализовать.
...но это невозможно даже теоретически.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 22:17 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Сергей Губанов писал(а):
...но это невозможно даже теоретически.


Ну и к чему эта упертость? Расскажете про эту теорию каким-нибудь хаскеллистам или хотя бы C++'ам.
Код:
struct X
{
   int &x;
};


Уверен, что на С++ вы умеете писать. Напишите код, при компиляции которого X::x останется непроиниченой.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 22:24 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2180
Откуда: Нижний Новгород
Vlad писал(а):
Сергей Губанов писал(а):
...но это невозможно даже теоретически.


Ну и к чему эта упертость? Расскажете про эту теорию каким-нибудь хаскеллистам или хотя бы C++'ам.
Код:
struct X
{
   int &x;
};


Уверен, что на С++ вы умеете писать. Напишите код, при компиляции которого X::x останется непроиниченой.


Легко!
Код:
#include <iostream>

struct X
{
   int &x;
};

int main()
{
    X* p_x = new X;
    std::cout << p_x->x << std::endl;
    return 0;
}


Компилируется. При запуске получившейся прелести имеем имеем segmentation fault.

PS.
Цитата:
$ g++ --version
g++ (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3)


Последний раз редактировалось Alexey Veselovsky Пятница, 30 Январь, 2009 22:32, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 22:30 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Alexey Veselovsky писал(а):
Компилируется. При запуске получившейся прелести имеем имеем segmentation fault.


Ужас какой. Вот что говорят нормальные компиляторы (VC/comeau):

error C2512: 'X' : no appropriate default constructor available

PS. Потом посмотрю на gcc.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 30 Январь, 2009 23:57 

Зарегистрирован: Воскресенье, 28 Май, 2006 22:12
Сообщения: 1470
По тому, что здесь уже наговорено - ряд мыслев...
1) Проблема с предложением Vlad-ом подобного рода ссылок - в логической нестыковке правил на счёт областей видимости переменных и возможных (или необходимых) местах инициализации таких ссылок.
2) В современных общеупотребительных императивных языках, ситуацию, максимально подходящую под идеи Vlad можно организовать ТОЛЬКО для случая, когда имеется какой-то набор статических данных, а на обработку они отправляются в процедуры с аргументами-ссылками... Почему - см. пункт 1.
3) Несколько дальше продвинулся на почве императивщины в направлении Vlad-овских мыслей язык Limbo. Там можно (по причине пересмотра синтаксиса и нотации) совмещать объявления с инициализацией... Собственно, Си/Си++ тоже поддерживает такой способ записи, но по причине 1 и 2 - никто всегда не будет этому следовать... Понятно, что в Обероне это в принципе нельзя ввести. Дело не в какой-то там "ущербности" оберонов... Работает опять-таки принцип "современного логического ассемблера ЯП-ия" : "всё делать явно!"... В том числе и - операции со ссылками...

Но мне видится довольно перспективным подход ОБЯЗАТЕЛЬНОСТИ (ДЛЯ ССЫЛОК!) СОВМЕЩЕНИЯ ОБЪЯВЛЕНИЯ С ИНИЦИАЛИЗАЦИЕЙ, как одного из элементов повышения надёжности. (Просто явно и NIL присваивать в объявлении!!!) Этим мы и кодогенерирующие части упрощаем и следование "всё - явно" придерживаемся!
Кстати, что-то тут (при таком походе) и в сторону сборщика мусора в плюсы идёт...Что-то по сему поводу в одной из статей по Лимбо и Инферно припоминается, на счёт более лёгкого отслеживания ссылочности и приближения этого всего к РВ...

Vlad-у - +2! За натолкновения на размышлизмы... На работе всё, что планировал - не успел сделать, но подумать было приятно... :twisted:


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 31 Январь, 2009 00:12 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Vlad писал(а):
PS. Потом посмотрю на gcc.


Посмотрел. Компилит. Если в структуру добавить конструктор или какой-нибудь не-POD мембер, то начинает нормально ругаться. Видимо какая-то обратная совместимость по багам + особенность POD структур.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 31 Январь, 2009 00:13 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2180
Откуда: Нижний Новгород
Vlad писал(а):
Vlad писал(а):
PS. Потом посмотрю на gcc.


Посмотрел. Компилит. Если в структуру добавить конструктор или какой-нибудь не-POD мембер, то начинает нормально ругаться. Видимо какая-то обратная совместимость по багам + особенность POD структур.


Я им забагрепортил это дело.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 154 ]  На страницу Пред.  1, 2, 3, 4, 5, 6, 7, 8  След.

Часовой пояс: UTC + 3 часа


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

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


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2020, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB