Передача автоматически типизированных переменных в функцию в D? - PullRequest
8 голосов
/ 28 июня 2010

Это не работает в D:

void doSomething(auto a, auto b){
    // ...
}

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

В любом случае, может ли это быть достигнуто любым другим способом?Я полагаю, что могу использовать ... и просмотреть список аргументов, но я вроде как создаю библиотеку для ленивых новичков и хочу, чтобы они могли легко создавать функции, не заботясь о типах данных.Я играю с идеей создания структуры под названием var, как

struct var{
   byte type;
   void* data
   // ...
}

// and overload like all operators so that a lazy devver can do

var doSomething(var a, var b){
   if(a == "hello")
       b = 8;
   var c = "No.:" ~ b ~ " says:" ~ a; 
   return c;
}

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

void doSomething(T, U)( T a, U b){
   // ...
}

Но теперь он уже не выглядит таким чистым.Может быть, я получаю все это задом наперед.Может быть, мое замешательство связано с моим убеждением, что auto - это динамический тип, сравнимый с var i javascript, но когда на самом деле это что-то другое?это, наверное, совсем другая тема, возможно ли ее создать?Или, может быть, есть ли библиотека с открытым исходным кодом?Может быть, клевета?

(PS. Да, может, ленивый девер это я:)

Ответы [ 4 ]

12 голосов
/ 28 июня 2010

Если doSomething является общим для любого типа a и b, то версия шаблона является правильным решением:

void doSomething(T, U)(T a, U b) {
    // etc.
}

Компилятор обнаружит типы, представленные T и U во время компиляции и сгенерируйте правильный код.

6 голосов
/ 28 июня 2010

Я просто добавлю, что что-то близкое к вашей идее полиморфизма типа времени исполнения (структура var) уже реализовано в модуле std.variant (только D2).

* 1005Кроме того, технически auto - это действительно ключевое слово, которое ничего не делает - оно используется там, где вам нужен модификатор типа без типа.Если вы не укажете тип, D выведет его для вас из выражения инициализации.Например, все эти работы:
auto i = 5;
const j = 5;
static k = 5;
2 голосов
/ 28 июня 2010

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

Вы можете игнорировать тип в D2, используя std.variant , и это может заставить код выглядеть так, как будто язык динамически типизирован.

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

Дополнительная информация о std.variant: Более подробно это еще сложнее, чем вы хотите.Например, чтобы присвоить значение типизированной переменной, требуется вызов метода.и вы не можете получить доступ к методам класса из ссылки.

int b = a.get!(int);
a.goFish() // Error Variant type doesn't have goFish method
1 голос
/ 29 июня 2010

Может быть, мое замешательство связано с моей верой в то, что auto - это динамический тип, сравнимый с var i javascript, но когда в действительности это что-то еще?

auto - это класс хранения . Фактически это класс хранения по умолчанию; это ничего не значит за пределами «это имеет класс хранения».

Теперь, если компилятор может однозначно определить тип, тогда все в порядке. В противном случае это ошибка:

auto i = 42;  // An integer literal is inferred to be of type 'int'.
auto j;       // Error!

Так что auto вообще не тип. Помните, что все это должно происходить во время компиляции, а не во время выполнения. Итак, давайте посмотрим на функцию:

auto add(auto a, auto b)
{
    return a + b;
}

Может ли компилятор автоматически определять типы a, b или значение return? Нету. В дополнение к примитивам, которые работают с оператором добавления (int, byte, double и т. Д.), Пользовательские типы могут перегрузить его и т. Д. Поскольку компилятор не может однозначно вывести любой из этих типов, это ошибка. Типы должны быть указаны в параметрах, потому что, как правило, они не могут быть выведены (в отличие от объявлений, например).

...