2014-01-26 8 views
1

Почему мы не можем вычислить декартово произведение двух неизменных диапазонов?Декартово произведение неизменяемых диапазонов

Следующий код:

import std.stdio; 
import std.algorithm; 

void main() { 

    immutable int[] B = [ 1, 2, 3 ]; 
    immutable int[] C = [ 4, 5, 6 ]; 
    auto BC = cartesianProduct(B, C); 

    writeln(BC); 
} 

Броски:

/usr/include/dmd/phobos/std/range.d(4199): Error: cannot modify struct result._ranges_field_1 Repeat!(immutable(int)) with immutable members 
/usr/include/dmd/phobos/std/range.d(4503): Error: template instance std.range.Zip!(immutable(int)[], Repeat!(immutable(int))) error instantiating 
/usr/include/dmd/phobos/std/algorithm.d(11674):  instantiated from here: zip!(immutable(int)[], Repeat!(immutable(int))) 
laurent_test.d(8):  instantiated from here: cartesianProduct!(immutable(int)[], immutable(int)[]) 
/usr/include/dmd/phobos/std/algorithm.d(11674): Error: template instance std.range.zip!(immutable(int)[], Repeat!(immutable(int))) error instantiating 
laurent_test.d(8):  instantiated from here: cartesianProduct!(immutable(int)[], immutable(int)[]) 
laurent_test.d(8): Error: template instance std.algorithm.cartesianProduct!(immutable(int)[], immutable(int)[]) error instantiating 

Futhermore, если второй но первый неизменны удаляется он работает.

В соответствии с реализацией phobos один из диапазонов как входного диапазона, а другой - forwardRange. Почему такие шаблонные ограничения?

+0

Обратите внимание, что люди, которые часто намереваются использовать, являются изменяемыми массивами неизменяемых элементов, например. 'Неизменны (INT) []'. 'immutable int []' эквивалентен 'immutable (int [])', который является более ограничительным, чем первый тип. Нельзя сказать, что это относится к вашей проблеме, тем более, что она не исправляет ее. –

ответ

2

Я определенно не специалист по D, но в прошлом году я спросил similar question, и этот answer from Jonathan M Davis был отличным.

TL; DR: Диапазон не может быть неизменны, потому что would't соблюдать 4 правила:

R r = void;  // can define a range object 
if (r.empty) {} // can test for empty 
r.popFront();  // can invoke popFront() 
auto h = r.front; // can get the front of the range 

Можете ли вы угадать culprint? popFront

+0

Действительно, static assert (isForwardRange! (Typeof (B))) не удалось. – matovitch

+0

Прошу прощения, я не принимаю этот ответ, потому что все не понимаю. Например, функция chain() работает, поскольку использует шаблон Unqual. Вычисление декартова продукта не требует popFront, не так ли? Зачем нам нужен ввод и передний диапазон? – matovitch

+2

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

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