функции, такие как map
и filter
диапазонов возврата, а не массивы, так просто назначаете массив не будет работать больше, чем назначая string
к wstring
будет работать. Они разные. И для многих функций на основе диапазона (включая map
и filter
) диапазоны, которые они возвращают, на самом деле ленивы, чтобы избежать ненужных вычислений, что делает их гораздо менее совместимыми с массивом. Решение состоит в использовании std.array.array
, который принимает диапазон и создает из него динамический массив. Таким образом, вы могли бы сделать
auto arr = array(map!process(origArray));
Однако я бы посоветовал не преобразовывать диапазон в массив, прежде чем на самом деле нужно, так как это может привести к ненужным вычислений, и это означает, что выделение нового массива. Если вам действительно нужен массив, то, во всяком случае, используйте std.array.array для преобразования диапазона, но работа в диапазоне часто может быть более эффективной, если вам не нужен фактический массив. Однако, если вы хотите преобразовать результат в массив static, в отличие от динамического, вам, вероятно, лучше просто назначить каждый элемент в цикле (и, возможно, вообще пропустить map
), поскольку с помощью std.array.array затем выделит динамический массив, который вы не будете использовать, как только вы назначили статический массив. Это пустая трата памяти.
Кроме того, имейте в виду, что использование статических массивов с функциями на основе диапазонов может быть рискованным тем, что они должны срезать статический массив, чтобы получить динамический массив для функций, основанных на диапазонах, и если этот динамический массив выходит за пределы области что статический массив был объявлен, тогда вы утечка ссылок на данные, которые больше не существуют. Например,
auto func()
{
int[5] arr;
return map!process(arr[]);
}
было бы очень плохо. Однако до тех пор, пока вы закончите использовать срез, и ничего больше не ссылается на него (включая любые диапазоны, которые могли быть созданы) перед тем, как вы выходите из области с помощью статического массива, вы должны быть в порядке. Это является что-то, чтобы быть осторожным, хотя.
Что касается вопроса о необходимости среза статических массивов, вы действительно должны спросить об этом как отдельный вопрос, но два существующих вопроса, которые относятся к нему: this one и this one. В значительной степени это связано с тем, что IFTI (Impression Function Template Instantiation) создает экземпляр, используя точный тип, который ему задан, а статический массив не является ни динамическим массивом, ни диапазоном, поэтому любая шаблонная функция, которая требует определенного динамического массива или диапазон не сможет скомпилироваться со статическим массивом. Компилятор будет неявно срезать статические массивы для преобразования их в динамические массивы для функций, которые явно принимают динамические массивы, но такого рода неявные преобразования не происходят с созданием шаблона, поэтому вы должны явно срезать статические массивы, чтобы передать их в диапазон - основанные функции.
Что касается вопроса об использовании foreach с индексами и диапазонами, опять же, вы не должны задавать несколько вопросов в одном и том же вопросе. Пожалуйста, размещайте отдельные вопросы по каждому интересующему вас вопросу. Что это сводится к тому, хотя в том, что
foreach(elem; range)
{
//stuff
}
получает опускают на что-то близко к
for(; !range.empty; range.popFront())
{
auto elem = range.front;
//stuff
}
И это не связано с показателями на всех. Это может быть быть изменением для создания переменной индекса для вас, но не всегда имеет смысл для диапазонов, чтобы их индекс итерации был таким же, как на каждой итерации (как это обычно бывает хорошо), и поэтому hasn не было сделано. Это достаточно просто, чтобы добавить свой собственный счетчик.
{
size_t i;
foreach(elem; range)
{
//stuff
++i;
}
}
opApply
не поддерживает использование индексов с Еогеасп, но это не диапазон, и не работает с функциями диапазона на основе.
Спасибо, Джонатан! Я знаю, что диапазоны и массивы являются разными типами, но полагал, что D может реализовать какое-то неявное преобразование, поскольку диапазоны конвертируются в массивы, если они конечны, а их элементы совместимы с типами массива. Я знаю разницу в распределении стека и кучи, а также вычисление и память накладных расходов на массирование, но спасибо за предупреждение в любом случае :) Также спасибо за разъяснение с IFTI - если бы я понял это правильно, в будущем это может измениться чтобы позволить неявные статические массивы среза, но теперь мы должны использовать этот путь из-за несовершенства. – toriningen
IFTI _might_ следует заменить на неявное преобразование статических массивов в динамические, но я сомневаюсь. По-прежнему необходимо, чтобы шаблонные функции принимали статические массивы (поэтому их преобразование для создания экземпляра всегда было бы плохим), и IFTI не пытается попробовать, пока не найдет неявное преобразование, которое работает (что было бы дорого и изменило бы семантика ряда шаблонов). Таким образом, я бы ожидал, что вам всегда придется срезать статические массивы, чтобы передать их функциям на основе диапазона, но в какой-то момент может быть достигнуто улучшение, по крайней мере, для устранения проблемы. –