Это не работает в 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
я JavaScript, но когда в действительности, это - что-то еще?
И если это не динамический тип, и это - вероятно, целая другая тема, действительно ли возможно создать то? Или есть ли, возможно, даже доступный lib с открытым исходным кодом? liblazy, возможно?
(PS. Да, возможно, ленивый devver - я:)
Добавлю только, что нечто близкое к вашей идее полиморфизма типов во время выполнения (структура var
) уже реализовано в модуле std.variant (только D2).
Кроме того, технически auto
на самом деле является ключевым словом, которое ничего не делает - оно используется там, где вам нужен модификатор типа без указания типа. Если вы не укажете тип, D выведет его за вас из выражения инициализации. Например, все эти выражения работают:
auto i = 5;
const j = 5;
static k = 5;
Если doSomething
является универсальным для любого типа a
и b
, то версия шаблона является правильным решением:
void doSomething(T, U)(T a, U b) {
// etc.
}
Компилятор будет обнаруживать типы, представленные T
и U
, во время компиляции и генерировать правильный код.
Может быть, мое замешательство связано с моим убеждением, что 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
и т. Д.), Определяемые пользователем типы могут перегрузить его и т. Д. на. Поскольку компилятор не может однозначно определить какой-либо из этих типов, это ошибка. Типы должны быть указаны в параметрах, потому что, как правило, они не могут быть выведены (в отличие, например, от объявлений).
Стоп, не делайте этого! Я боюсь, что если вы будете игнорировать типы на ранних этапах, вам будет сложнее их освоить, особенно учитывая, что D не является динамически типизированным. Я считаю, что типы важны даже в динамических языках.
Вы можете игнорировать типы в D2, используя std.variant, и это может заставить код выглядеть так, как будто язык динамически типизирован.
Вы правы в использовании Template, но не auto. D позволяет вам использовать это слово во многих обстоятельствах, таких как тип возврата, поскольку D имеет очень хорошую систему для вывода типа. Параметры - это то, что не поставляется с дублирующей информацией для вывода типа.
Дополнительная информация о std.variant: Если посмотреть на это подробнее, то это все еще сложнее, чем то, что вы хотите. Например, для присвоения значения типизированной переменной требуется вызов метода. и вы не можете получить доступ к методам класса из ссылки.
int b = a.get!(int);
a.goFish() // Error Variant type doesn't have goFish method