OberonCore
https://forum.oberoncore.ru/

Суровый баг в XDS Oberon
https://forum.oberoncore.ru/viewtopic.php?f=30&t=942
Страница 1 из 1

Автор:  Александр Ильин [ Среда, 09 Апрель, 2008 23:27 ]
Заголовок сообщения:  Суровый баг в XDS Oberon

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

Пусть у нас есть тип Item и его наследник ItemExt:
Код:
TYPE
   Str: ARRAY 64 OF CHAR;
   Item = POINTER TO ItemDesc;
   ItemDesc = RECORD next: Item; name: Str END;
   ItemExt = POINTER TO RECORD (ItemDesc) field: INTEGER END;
Item'ы объединены в односвязанный список и поименованы. Важно, чтобы в списке элементы были отсортированы по имени. Помимо ItemExt есть много других наследников от Item, поэтому захотел я написать единую процедуру Add, которая будет добавлять новый элемент сразу в нужное место списка:
Код:
PROCEDURE Add (VAR list: Item; i: Item);
BEGIN
   IF list = NIL THEN
      list := i
   ELSE
      (* добавляем i в список list*)
   END
END Add;
Идея процедуры такова: подаём первым параметром переменную-корень списка. Если список пуст (корень = NIL), то инициализируем корень первым элементом i. В противном случае добавляем i в существующий список, возможно, изменяя корень - если нужно вставить i в самое начало. Далее я создал список типа ItemExt, но как только я попытался вызвать Add (list, new), то компилятор на меня заругался, поскольку в качестве list я хотел передать ему ItemExt, что не соответствует VAR-параметру типа Item (предок). В самом деле, мало ли что там процедура может присвоить. Пришлось переделать, возвращая новый корень в результате:
Код:
PROCEDURE Add (list, i: Item): Item;
BEGIN
   IF list = NIL THEN
      RETURN i
   ELSE
      (* добавляем i в список list*)
      RETURN list
   END
END Add;
Соответственно, на выходе возникла необходимость в охране типа:
Код:
VAR list, new: ItemExt;
...
   NEW (new); new.name := ...
   list := Add (list, new)(ItemExt);

И вот тут случилось самое интересное. Оказывается, чтобы применить охрану типа к результату процедуры, XDS по-тихому вызывает процедуру второй раз! Хорошо, что у меня в Add был ASSERT (i.next = NIL), а то поди долго бы искал, почему зацикливается проход по списку.

Получается, что надо мне писать теперь
Код:
tmp := Add (list, new); list := tmp(ItemExt);
а это уже совсем далеко от элегантности первого решения. Подскажите, если кто с подобными списками работал, как мне быть. Общая задача такова: каждый список содержит только объекты одного типа, просто не хочется дублировать для каждого типа процедуру Add. У меня вариант только один: всегда создавать неиспользуемый корень списка, чтобы исключить причину для использования VAR-параметра в первом примере и возвращения результата процедуры во втором (т.е. исключить необходимость изменения корня списка).

Автор:  Vlad [ Четверг, 10 Апрель, 2008 00:45 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Александр Ильин писал(а):
Нашёл сегодня при написании тестового приложения. Заодно опишу задачу, может быть кто-то посоветует более элегантное решение.


Отделите тип "список" от типа "элемент списка". Все сразу станет понятнее и обобщеннее.

P.S. Предлагаю оберонщикам, перед тем как начать захватывать мир, завести хоть сколько-нибудь стандартную библиотеку контейнеров. Хотя бы уровня упоминавшейся здесь когда-то "ГРОМ"'. Это ж детский сад - для каждой задачи городить еще один более удобный и красивый список...

Автор:  Info21 [ Четверг, 10 Апрель, 2008 03:12 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Vlad писал(а):
P.S. Предлагаю оберонщикам, перед тем как начать захватывать мир, завести хоть сколько-нибудь стандартную библиотеку контейнеров. Хотя бы уровня упоминавшейся здесь когда-то "ГРОМ"'. Это ж детский сад ...


Детский сад -- не понимать своего непонимания.
Тоже мне, "уровень".

Это напоминает плодящиеся системы компьютерной алгебры на С++, в которых есть "всё", и которыми невозможно пользоваться.

За 15 лет лично у меня не появилось необходимости в "стандартной библиотеке".
Для конкретных классов подзадач -- да. Но там, как правило, всё сделать легко, и никакой необходимости в очередном универсальном монстре не просматривается.

Скрывать всё вообразимое разнообразие опцый за каким-то монструозным интерфейсом, который прикрывает поле next -- глупость.

Автор:  Александр Ильин [ Четверг, 10 Апрель, 2008 08:07 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Vlad писал(а):
Отделите тип "список" от типа "элемент списка". Все сразу станет понятнее и обобщеннее.

Спасибо, подумаю.

Автор:  Евгений Темиргалеев [ Четверг, 10 Апрель, 2008 11:33 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Vlad писал(а):
Отделите тип "список" от типа "элемент списка". Все сразу станет понятнее и обобщеннее.

Понятнее? "На вкус и цвет товарища нет" :) Я бы еще подумал - выносить голову списка в отдельный тип или хранить её в элементе списка, затрачивая на каждый список лишний ARRAY 64 OF CHAR. Как раз чтобы не иметь дела с двумя типами. При этом вся обработка упрощается, т.к. у любого элемента есть предыдущий и не надо писать IF list = NIL

Такой подход наиболее удобен, если список сначала строится а потом используется. Сначала делаем голову, чтобы не писать IF list = NIL ... После построения её отрубаем list := list.next и возвращаем безголовый список :)

Автор:  Александр Ильин [ Четверг, 10 Апрель, 2008 15:10 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Евгений Темиргалеев писал(а):
После построения её отрубаем list := list.next и возвращаем безголовый список :)
Евгений, присуждаю вам приз "5 баллов" за отличную подсказку! Это именно то, что нужно в моём случае : )

Автор:  Сергей Губанов [ Четверг, 10 Апрель, 2008 15:13 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Поле next имеет тип Item, значит и переменная list тоже должна иметь тип Item, а не ItemExt.

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

Объявляем list как просто Item:
Код:
VAR list: Item;
  new1: ItemExt1;
  new2: ItemExt2;
...
Add(list, new1);
Add(list, new2);

и приведения типов в процедуре Add делать не надо.

Автор:  Vlad [ Четверг, 10 Апрель, 2008 19:24 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Info21 писал(а):
За 15 лет лично у меня не появилось необходимости в "стандартной библиотеке".


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

Автор:  Vlad [ Четверг, 10 Апрель, 2008 19:44 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Евгений Темиргалеев писал(а):
Vlad писал(а):
Отделите тип "список" от типа "элемент списка". Все сразу станет понятнее и обобщеннее.

Понятнее? "На вкус и цвет товарища нет" :)


Понятнее и обобщеннее. Список - это структура, ввод соответствующего типа выражает это явно в коде. И это позволит написать функцию работы со списком один раз. Структура с полем "next" - это фиг знает что такое. Это может быть списком, а может и нет.

Евгений Темиргалеев писал(а):
Такой подход наиболее удобен, если список сначала строится а потом используется. Сначала делаем голову, чтобы не писать IF list = NIL ... После построения её отрубаем list := list.next и возвращаем безголовый список :)


Похоже у нас несовместимые понятия "удобства" и "наглядности".

Автор:  Александр Ильин [ Пятница, 11 Апрель, 2008 00:24 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Сергей Губанов писал(а):
... и приведения типов в процедуре Add делать не надо.
Просто нужно было получить список, корень которого имеет тип ItemExt. Вы правы, можно сделать переменную типа Item в качестве временного корня, а потом присвоить её значение в нужную переменную, применив охрану типа один раз.

Решение с подставным корнем укоротило процедуру Add почти вдвое: не надо обрабатывать особый случай (list = NIL), всё делается одним циклом без особых случаев.

При отрубании головы списка хотел использовать такой код:
Код:
list := list.next
Компилятор ругается, что list имеет тип ItemExt, а list.next - просто Item. Поставил охрану:
Код:
list := list.next (ItemExt)
После этого неоднократно столкнулся с ошибкой времени выполнения при охране типа в случае, когда list.next = NIL. Пришлось писать так:
Код:
IF list.next # NIL THEN list := list.next (ItemExt) END

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

Автор:  Александр Ильин [ Пятница, 11 Апрель, 2008 00:31 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Vlad писал(а):
Понятнее и обобщеннее. Список - это структура, ввод соответствующего типа выражает это явно в коде. И это позволит написать функцию работы со списком один раз.
Я и так написал один раз.
Код:
PROCEDURE Add (list, i: Item);
(* Add new item i to the list. The list is sorted by name, ascending. The first item in the list is a fake root. *)
BEGIN
   ASSERT (i # NIL, 20);
   ASSERT (i.next = NIL, 21);
   ASSERT (i.name # '', 22);
   ASSERT (list # NIL, 23);
   ASSERT (list.name = '', 24);
   WHILE (list.next # NIL) & (i.name > list.next.name) DO
      list := list.next
   END;
   i.next := list.next;
   list.next := i
END Add;

Автор:  Vlad [ Пятница, 11 Апрель, 2008 01:51 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Александр Ильин писал(а):
Я и так написал один раз.


То что вы написали работает только для Item и его наследников. Т.е., все что угодно в список уже не положишь. Можно конечно завести Item, в который можно что-то класть, но ради чего такие неудобства?

Автор:  Александр Ильин [ Пятница, 11 Апрель, 2008 07:09 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Vlad писал(а):
Отделите тип "список" от типа "элемент списка".
Vlad писал(а):
То что вы написали работает только для Item и его наследников.
А если я разделю список (List) и элемент списка (Item), разве это будет работать не только для Item и его наследников?

Автор:  Info21 [ Пятница, 11 Апрель, 2008 08:19 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Vlad писал(а):
Это только лишний раз доказывает, что к программированию вы имеете такое же отношение, какое я к физике.

Вот видите, Vlad, какие клеветы Вы постоянно себе позволяете. Нежно называя себя "несогласным". А мои возражения на Ваши клеветы называя разными словами.

Всё-таки к программированию я имею гораздо большее отношение, чем Вы -- к физике.

1) Вы же не обероновские коды читаете в указанных количествах.
2) Прямую реализацию простого списка (кои составляют подавляющее большинство всех списков) даже с какой-то особенностью на Обероне прочесть проще, чем вспоминать опции какой-нибудь монструозной "универсальной" библиотеки.
3) Если библиотека содержит опции на все случаи жизни, то программеры сумеют наварить там каши ничуть не слабее, чем с одним полем next.

Автор:  Valery Solovey [ Пятница, 11 Апрель, 2008 10:29 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

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

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

Автор:  Александр Ильин [ Пятница, 11 Апрель, 2008 18:54 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Александр Ильин писал(а):
После этого неоднократно столкнулся с ошибкой времени выполнения при охране типа в случае, когда list.next = NIL. Пришлось писать так:
Код:
IF list.next # NIL THEN list := list.next (ItemExt) END
Проглядел ошибку. Правильный код отрубания головы списка даже ещё длиннее:
Код:
IF list.next # NIL THEN list := list.next (ItemExt) ELSE list := NIL END

Автор:  Vlad [ Пятница, 11 Апрель, 2008 18:56 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Александр Ильин писал(а):
А если я разделю список (List) и элемент списка (Item), разве это будет работать не только для Item и его наследников?


Если Item будет ANYREC, то будет работать для всего ;)

P.S. А вот чего делать в оригинальном обероне - я не знаю. Как описать работу с любым типом?

Автор:  Vlad [ Пятница, 11 Апрель, 2008 19:32 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Info21 писал(а):
Vlad писал(а):
Это только лишний раз доказывает, что к программированию вы имеете такое же отношение, какое я к физике.

Вот видите, Vlad, какие клеветы Вы постоянно себе позволяете. Нежно называя себя "несогласным". А мои возражения на Ваши клеветы называя разными словами.


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

Info21 писал(а):
Всё-таки к программированию я имею гораздо большее отношение, чем Вы -- к физике.


Хорошо, какое именно отношение вы имеете к программированию? Я еще ничего ценного в ваших статьях/высказываниях не почерпнул. Ничего кроме критики необеронов. Читая Илью Ермакова, несмотря на его не меньшую одержимость оберонами, можно расширить свое понимание в области программирования. Ваше отношение к программированию для меня, как стороннего наблюдателя, примерно такое: физик использует BB для решения своих задач. С тем же успехом я могу ставить некие "физические опыты" у себя на балконе и причислять себя к физике :)

Info21 писал(а):
1) Вы же не обероновские коды читаете в указанных количествах.


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

Info21 писал(а):
2) Прямую реализацию простого списка (кои составляют подавляющее большинство всех списков) даже с какой-то особенностью на Обероне прочесть проще, чем вспоминать опции какой-нибудь монструозной "универсальной" библиотеки.


Я видел тексты BB. Не проще.

Info21 писал(а):
3) Если библиотека содержит опции на все случаи жизни, то программеры сумеют наварить там каши ничуть не слабее, чем с одним полем next.


"Хорошие" программеры сумеют написать более читабельный код. "Плохим" - и одно поле next не помешает написать нечто несопровождаемое.

Автор:  Info21 [ Суббота, 12 Апрель, 2008 14:32 ]
Заголовок сообщения:  Re: Суровый баг в XDS Oberon

Vlad писал(а):
...

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

Но к троллингу у Вас природный талант, отдаю должное.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/