Автор Тема: Generic Oberon  (Прочитано 8976 раз)

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Generic Oberon
« : Август 28, 2013, 06:44:33 am »
Даёшь дженерики! Даёшь инициализацию массивов!! Даёшь динамические массивы!!! )))

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

Ну как вариант -- как-то так:

Lightweight Parametric Polymorphism for Oberon (Paul Roe and Clemens Szyperski)
Цитировать
By combining Oberon's inclusion polymorphism (subtyping) with parametric polymorphism, the map procedure can be abstracted to work for entire families of collections, not only lists.
TYPE Ptr(A) = POINTER TO A;

TYPE Proc(A) = PROCEDURE (x: Ptr(A));

TYPE Collection(A) = Ptr(CollectionDesc(A));
     CollectionDesc(A) = RECORD
        elem: Ptr(A)
     END;

     List(A) = Ptr(ListDesc(A));
     ListDesc(A) = RECORD (CollectionDesc(A))
        next: List(A)
     END;

     Tree(A) = Ptr(TreeDesc(A));
     TreeDesc(A) = RECORD (CollectionDesc(A))
        left, right: Tree(A)
     END;

PROCEDURE <A> (c: Collection(A)) Map (p: Proc(A));
BEGIN p(c.elem)
END Map;

PROCEDURE <A> (l: List(A)) Map (p: Proc(A));
BEGIN
  l.Map^(p); (* "super call" to overridden procedure *)
  IF l.next # NIL THEN l.next.Map(p) END
END Map;

PROCEDURE <A> (t: Tree(A)) Map (p: Proc(A));
BEGIN
  IF t.left  # NIL THEN t.left.Map(p)  END;
  l.Map^(p);
  IF t.right # NIL THEN t.right.Map(p) END
END Map;
For example, it is now possible to abstractly map Rotate over a collection of points Collection(PointDesc), regardless of whether the collection is actually a list, a tree, or any other structure derived from the base type Collection(A).
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Generic Oberon
« Ответ #1 : Август 28, 2013, 01:17:19 pm »
Без вникания в тему сказать тяжело, но мне кажется, что мой вариант тоже будет работать
TYPE
ArrList(T) = RECORD a: ARRAY OF T; size: INTEGER END;

PROCEDURE (l: ArrList) Add(i: T);
BEGIN
IF l.size >= LEN(l) THEN l.a := Expand(l.a) END;
l.a[size] := i;
size := size + 1
END Add;

PROCEDURE (l: ArrList) Get(i: INTEGER): T;
BEGIN
RETURN l.a[i]
END Get;

PROCEDURE Do;
VAR  l: List(MyType);
item: MyType;
BEGIN
Init(item);
InitList(l);
l.Add(item);
END;
Впридачу, он ещё и локаничнее.

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Generic Oberon
« Ответ #2 : Август 28, 2013, 01:26:59 pm »
Без вникания в тему сказать тяжело, но мне кажется, что мой вариант тоже будет работать
PROCEDURE (l: ArrList) Add(i: T);В придачу, он ещё и лаконичнее.

А откуда здесь тип T взялся?
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Generic Oberon
« Ответ #3 : Август 28, 2013, 03:20:40 pm »
А откуда здесь тип T взялся?
Из объявления типа:ArrList(T) = RECORD a: ARRAY OF T; size: INTEGER END;

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Generic Oberon
« Ответ #4 : Август 28, 2013, 05:17:01 pm »
А откуда здесь тип T взялся?
Из объявления типа:ArrList(T) = RECORD a: ARRAY OF T; size: INTEGER END;

Ну и как у Вас тут связаны тип и процедуры?
TYPE
ArrList(T) = RECORD a: ARRAY OF T; size: INTEGER END;

PROCEDURE (l: ArrList) Add(i: T);
BEGIN
IF l.size >= LEN(l) THEN l.a := Expand(l.a) END;
l.a[size] := i;
size := size + 1
END Add;

PROCEDURE (l: ArrList) Get(i: INTEGER): T;
BEGIN
RETURN l.a[i]
END Get;

Т в объявлениях процедур выскакивает как чёртик из табакерки, нарушая принцип наименьшего удивления...
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Generic Oberon
« Ответ #5 : Август 28, 2013, 06:12:06 pm »
Цитировать
   TYPE
      ArrList(T) = RECORD a: ARRAY OF T; size: INTEGER END;
            
   PROCEDURE (l: ArrList) Add(i: T);
   BEGIN
      IF l.size >= LEN(l) THEN l.a := Expand(l.a) END;
      l.a[size] := i;
      size := size + 1
   END Add;

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Generic Oberon
« Ответ #6 : Август 28, 2013, 07:07:27 pm »
А если программист сделает так:

   TYPE
      ArrList(T) = RECORD a: ARRAY OF T; size: INTEGER END;

  ... тонна кода ...

   PROCEDURE (l: ArrList) Add(i: M);
   BEGIN
      IF l.size >= LEN(l) THEN l.a := Expand(l.a) END;
      l.a[size] := i;
      size := size + 1
   END Add;

Скажем, что он сам себе злой буратина?
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Generic Oberon
« Ответ #7 : Август 28, 2013, 07:09:12 pm »
Кроме того, процедуры же могут содержать несколько полиморфных параметров:

PROCEDURE <A, B, C> Foo(a: A; b: B): C;
...

Как тут быть с Вашим подходом?
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Generic Oberon
« Ответ #8 : Август 28, 2013, 08:13:49 pm »
Вообще, если уж улучшать систему типов оберона, добавляя в неё дженерики, то надо бы избавиться и от таких рудиментов как
TYPE PList = POINTER TO List;
     List  = RECORD
       elem: SomeType;
       next: PList
     END;
Во всех современных языках делается так:
TYPE List = RECORD
       elem: SomeType;
       next: POINTER TO List
     END;

Кроме того, предложенный Шиперским вариант обозначения дженериков различается у типов и процедур, это неконсистентный дизайн, имхо.
<A> пошло от всяких сишарпов и с++, на треугольные скобки накладывается лишний функционал, а, например, фигурные скобки вообще не используются.
И, кстати, в обероне-07 вроде нет процедур, привязанных к записям, как в обероне-2?

Короче, пример из первого сообщения может выглядеть как-то так:
TYPE Proc{A} = PROCEDURE (x: A);

TYPE Collection{A} = RECORD
        elem: A
     END;

     List{A} = RECORD (Collection{A})
        next: POINTER TO List{A}
     END;

     Tree{A} = RECORD (Collection{A})
        left, right: POINTER TO Tree{A}
     END;

PROCEDURE Map{A} (c: Collection{A}; p: Proc{A});
BEGIN p(c.elem)
END Map;

PROCEDURE Map{A} (l: List{A}; p: Proc{A});
BEGIN
  Map{A}(l, p); (* "super call" to overridden procedure *)
  IF l.next # NIL THEN Map{A}(l.next, p) END
END Map;

PROCEDURE Map{A} (t: Tree{A}; p: Proc{A});
BEGIN
  IF t.left  # NIL THEN Map{A}(t.left,  p) END;
  Map{A}(l, p);
  IF t.right # NIL THEN Map{A}(t.right, p) END
END Map;

Правда, тут получилась перегрузка имён процедур, а как известно всем образованным программистам, лучший способ пергрузочного полиформизма -- это классы типов ))

ЗЫ. С другой стороны, фигурные скобки можно было бы отвести под инициализаторы массивов и записей. Нагружать этой функцией круглые или прямоугольные тоже не очень.

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

PPPS. А если ещё и ключевые слова в нижнем регистре, да ещё и light-syntax (значимые отступы)... Короче, это уже нельзя будет назвать Обероном. В лучшем случае какой-нить Титанией )))
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Generic Oberon
« Ответ #9 : Август 28, 2013, 08:14:13 pm »
   PROCEDURE (l: ArrList) Add(i: M);
...
Скажем, что он сам себе злой буратина?
Ну да. А что странного? Ошибка же. Или как?

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Generic Oberon
« Ответ #10 : Август 28, 2013, 08:15:37 pm »
Кроме того, процедуры же могут содержать несколько полиморфных параметров:
...
Как тут быть с Вашим подходом?
Так же, как и у Шиперского.

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Generic Oberon
« Ответ #11 : Август 28, 2013, 08:16:00 pm »
   PROCEDURE (l: ArrList) Add(i: M);
...
Скажем, что он сам себе злой буратина?
Ну да. А что странного? Ошибка же. Или как?
Место, где указано правильное написание этого параметра, слишком далеко от места его употребления. Чревато ошибками, что нежелательно...
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Generic Oberon
« Ответ #12 : Август 28, 2013, 08:22:36 pm »
Вообще, если уж улучшать систему типов оберона, добавляя в неё дженерики, то надо бы избавиться и от ... рудиментов
Я, предлагая свой вариант, пытался также пояснить, что это лишь первый набросок. Возможно, есть вариант что-то улучшить. Однако, я считаю свой вариант более логичным, чем у Шиперского.

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Generic Oberon
« Ответ #13 : Август 28, 2013, 08:37:31 pm »
... фигурные скобки вообще не используются.

Чёртовы множества, никогда ими не пользовался и совсем забыл, что в оберонах они задаются в этих фигурных скобках...
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Generic Oberon
« Ответ #14 : Август 28, 2013, 08:45:59 pm »
Вообще, если уж улучшать систему типов оберона, добавляя в неё дженерики, то надо бы избавиться и от ... рудиментов

Я, предлагая свой вариант, пытался также пояснить, что это лишь первый набросок. Возможно, есть вариант что-то улучшить. Однако, я считаю свой вариант более логичным, чем у Шиперского.

В обероне-07 нет методов, вместо них процедурные переменные с явной инициализацией (в какой-нибудь фабрике).
То есть такой код для Оберона-07 невалиден:

PROCEDURE (t: Tree) Insert (node: Tree); ...

Вообще, это же похоже на сишарпные методам расширений (extension method), а это опять же полпути к классам типов...
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…