рекурсивные определения типов

Landstreicher

Как в различных языках программирования объявляются взаимно рекурсивные типы по типу ?
Допустим, я хочу объявить типы A и B так, что объявление одного использует другой.
Например (в синтаксисе OCaml):

type A = Data of int | Pair of B * B
type B = Name of string | Triple of A * A * A

В первую очередь интересуют ML, Haskell, Java, C#.
Насколько можно такие объявления разносить по разным файлам (модулям)?

6yrop

Java, C#.
без каких-либо ограничений

6yrop

точнее в Java есть ограничение — один публичный класс в файле

Landstreicher

> без каких-либо ограничений
Я правильно понимаю, что тогда значения хранятся по ссылке?
Например, иначе как такое компилировать
struct A
{
int x;
A next;
};
получается: sizeof(A)>=sizeof(int)+sizeof(next)>sizeof(A) -> противоречие.

6yrop

да, со структурами такое нельзя
Struct member 'My.A.next' of type 'My.A' causes a cycle in the struct layout

bleyman

В шарпе все структуры к тому же по умолчанию sealed (то есть от них нельзя наследоваться).
А про приколы с самонаследованием генериков (это шарповые типа темплейты) я недавно писал - смешная штука, но может оказаться полезной.

garikus

Component Pascal:

TYPE
A = POINTER TO RECORD
i: INTEGER;
b: B
END;
B = POINTER TO RECORD
s: POINTER TO ARRAY OF CHAR;
a: A
END;

Импорт модулей односторонний, поэтому типы A и B по модулям разнести нельзя (модуль в Component Pascal - это примерно то же самое, что namespace в C++).

Landstreicher

> A = POINTER TO RECORD
Это указатель? Что делать, если я хочу не указатель, а саму структуру?
Например, класс RCBase<T> из приведенного примера включает T.

Landstreicher

> В шарпе все структуры к тому же по умолчанию sealed (то есть от них нельзя наследоваться).
М.б. туплю, но не совсем понимаю как это связано с наследованием. Изначально речь шла о включении одного типа в другой как поля в структуре. Хотя обобщить это на ОО - тоже интересная мысль, как-то раньше не задумывался.

Landstreicher

> Импорт модулей односторонний, поэтому типы A и B по модулям разнести нельзя (модуль в Component Pascal - это примерно то же самое, что namespace в C++).
Если так, то возникает вопрос: можно ли в Component Pascal реализовать класс наподобие shared_ptr<T> и A из примера, приведенного в первом посте? Насколько я понимаю, нельзя, там зависимость циклическая. Или есть какие-то хитрые методы выкрутиться?

Dasar

С чего ты взял, что у тебя в примере (который с shared_ptr) есть циклическая зависимость?
Вообще, в том же C++ есть разные зависимости между типами:
a. необходимо только знать, что такой тип есть
b. необходимо знать размер типа
c. необходимо знать реализацию типа
Далее разные зависимости могут требоваться из разных мест:
из определения типа:
1. Поля-ссылки (зависимость a)
2. Поля по значению (зависимость b)
из определения методов
1. зависимость a
из тела методов
1. зависимость a, b, c
соответственно, если каждое определение класса разбивать на три части:

//part1
class A;
//part2
class A
{
  int z;
  void Method;
};
//part3
void A::Method{}

то никаких циклических зависимостей - нет, если ты только, конечно, не хочешь создать class бесконечного размера.
Современные языки - это разбиение делают сами.
Устаревшие языки - такое разбиение заставляют делать программиста.
Оставить комментарий
Имя или ник:
Комментарий: