Войти в систему

Home
    - Создать дневник
    - Написать в дневник
       - Подробный режим

LJ.Rossia.org
    - Новости сайта
    - Общие настройки
    - Sitemap
    - Оплата
    - ljr-fif

Редактировать...
    - Настройки
    - Список друзей
    - Дневник
    - Картинки
    - Пароль
    - Вид дневника

Сообщества

Настроить S2

Помощь
    - Забыли пароль?
    - FAQ
    - Тех. поддержка



Пишет kouzdra ([info]kouzdra) в [info]programming
@ 2005-11-02 00:06:00


Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Для затравки
Представление данных в O'Caml (и вообзще -ML):

На самом деле - оно очень красиво. Что самое забавное - на С изобразить
это можно, но задолбаешся. Итак:

1) никакого RTTI в O'Caml нет. Нет настолько, что сделать downcasting в
объектном расширении просто невозможно технически.

2) Представление данных там стольже прямолинейно и тупо как в Pascal.

3) Что есть - есть следующее:

Все типызначения представляются в O'Caml одним словом и делятся на boxed
и unboxed. Boxed - это те, которые лежат в куче, а представляются адресом в оной.
Unboxed - представляются своим физическим значением, сдвинутым влево на 1 бит и
1 в младшем бите. Потому, собственно, int в O'Caml не 31, а 30 битов.

Unboxed values - int, char, bool, unit (да - у него есть значение - нолик),
и элементы union's (АТД) без "of ...".

Boxed - все остальное. Соотвественно как представляются

type 'a Tree = E | N of 'a tree * 'a * 'a tree

Вариант E - просто 0 (с учетом сдвига и битика - 1)
вариант N - адрес блока, в котором лежит три слова - элементы узла.
Сам тэг (1) лежат в управляющем слове по смещению -4 от адреса.

Вот. Общая идея, надеюсь, понятна. На самом деле вся "информация о типах" в run-time
сводится к этому самому младжему битику, который отличает значение от адреса. Более
- ничего. Какие-то вещи (вроде сериализации или полиморфного сравнения) на этом
сделать можно. Но вообще-то мало что можно.


(Читать комментарии) - (Добавить комментарий)


[info]kouzdra
2005-11-02 11:00 (ссылка)
Что-то похожее есть в Haskell. Но там хитрее (и, по моему, лучше):
Там "классы типов", то есть некий интерфейс, которым обладает тип.
Ну классика:
   class Eq a where (==): a -> a -> Bool

И, скажем, реализация;
   instance Eq a => Eq [a] where a == b = ...

То есть тут instance задает правило для реализации сравнения
списков, если есть сравнение элементов.

Кайф в возможности писать вещи вроде:
count: Eq a => a - > [a] -> Int
count e [] = 0
count e (a:b) | a == e    = 1 + count e b
count e (a:b) | otherwise = count e b


Реализация простая - "предикат" (Eq a => ...) в типе значения (функции)
означает, что у функции есть неявный параметр - табличка с "интерфейсом".
А всякие instance задают правила, позволюще ее получить.

С одной стороны - тут интерфес полностью отвязан от типа (это что-то вроде "точки
зрения на тип"), с другой - все хорошо. Наследованию соотвестует описание
класса, у которого "пререквизитом" является набор других классов.

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

Система мне очень нравится, правда в Haskell как всегда навернули ее
сверх меры.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]potan
2005-11-02 12:00 (ссылка)
Я считал что в OCaml классы так же сделаны. Иначе как реализовать
# let f = fun c -> c#xex;;
val f : < xex : 'a; .. > -> 'a = <fun>

(Ответить) (Уровень выше)


[info]qwerty
2005-11-02 12:17 (ссылка)
Ага. В своем объектном Форте я тоже так делал, но не смог раскрутиться. Сейчас, наверно, смог бы за счет ума компилятора.

Кажется, я бы сделал даже иначе - каждое значение состоит как минимум из "головы", из которой могут расти "хвосты" (Г.Цейтин уже над этим 15 дет назад отсмеялся). Тип головы должен быть в точности выводиться во время компиляции. Каждый хвост снабжается константным тегом представления. В голове логически обязан быть представленный ссылкой интерфейс. Физически умный компилятор может интерфейс извести - например, если известно, что для данного типа его подменять запрещено. Динамика типов делается через подмену интерфейсов, каковые должны быть совместимы с типом. Если очень хочется, можно завести подтипы на головах, но подтипы очень ограниченные - тип в точности известен, присваивать надтипу можно (при условии совместимости ьекущего интерфейса с надтипом), но при этом надтип и получается путем отбрасывания полей.

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

(Ответить) (Уровень выше)


(Читать комментарии) -