2015-01-14 4 views
3

Я пытаюсь сделать простое использование типов в Nim. Пожалуйста, имейте в виду, что я только использовал Nim с утра, так что, возможно, я делал что-то глупое.Типовые классы в Nim

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

type 
    Generator*[T] = generic x 
    next(var x) is T 

    BoundedGenerator*[T] = generic x 
    x is Generator[T] 
    min(x) is T 
    max(x) is T 

У меня также есть такой пример, скажем LinearCongruentialGenerator.

Скажите, что я хочу использовать это, чтобы определить генератор Uniform, который производит значения поплавка в интервале. Я попытался

type Uniform* = object 
    gen: BoundedGenerator[int] 
    min_p: float 
    max_p: float 

proc create*(gen: BoundedGenerator[int], min: float, max: float): Uniform = 
    return Uniform(gen: gen, min_p: min, max_p: max) 

я опускаю очевидные определения next, min и max.

выше, однако, не компилируется из-за Error: 'BoundedGenerator' is not a concrete type

Если я явно поставил LinearCongruentialGenerator вместо BoundedGenerator[int], Everyting компилирует, но, конечно, я хочу, чтобы иметь возможность переключаться более сложные генераторы.

Может ли кто-нибудь помочь мне понять ошибку компилятора?

ответ

6

Классы классов в Nim не используются для создания абстрактных полиморфных типов, как в случае с типами классов Haskell и интерфейсами C++. Вместо этого они гораздо больше похожи на предложение концепций для C++. Они определяют набор требований к произвольному типу, которые могут использоваться в качестве критериев разрешения перегрузки для общих функций.

Если вы хотите работать с абстрактными типами, вы можете либо определить иерархию типов с общим базовым типом, либо использовать методы (которые используют multiple dispatch), или вы можете свернуть свое собственное решение на основе vtable. В будущем пользовательские классы классов получат возможность автоматически преобразовывать согласованные значения в другой тип (во время разрешения перегрузки). Это упростит использование подхода vtable, поскольку значения типов с совместимыми интерфейсами будут преобразованы в «указатель жира», переносящий виртуальную таблицу на внешний объект (с учетом того, что многие указатели с различными абстрактными типами могут быть созданы для того же объект). Я буду применять эти механизмы в ближайшие несколько месяцев, надеюсь, до выпуска 1.0.

Araq (основной автор Nim) также имеет некоторые планы по оптимизации определенного типа групп замыканий, соединенных вместе с более дешевым представлением, где среда закрытия распределяется между ними, а конечный результат довольно близок к традиционному C++ - как объект, поддерживающий vtable.

+0

Оба мультиметода и vtables используют динамическую отправку во время выполнения, но, похоже, в большинстве случаев это необязательно. Фактически, как правило, большая часть информации о типе известна во время компиляции, и разрешение правильной реализации может быть статическим. На самом деле, я думаю, что теперь я лучше понимаю эту ошибку, и мне кажется, что она не связана с различием между классными классами Nim и интерфейсами C++. Скорее, я думаю, что Nim не может определить правильный размер для 'Uniform', учитывая, что реализации' BoundedGenerator [int] 'могут иметь переменные размеры. – Andrea

+1

Ну, я должен знать, что означает эта ошибка, поскольку я добавил ее в компилятор :) BoundedGenerator [int] не является конкретным типом, который может быть создан - это просто проверяемое описание категории типов, которые ведут себя как BoundedGenerators. Вы можете создать много конкретных типов объектов, которые соответствуют этому описанию. – zah

Смежные вопросы