Вызов sort после отображения в массиве - PullRequest
0 голосов
/ 05 февраля 2019

Я хочу отсортировать строки, прочитанные из stdin по длине строки, после обрезки пробелов.Код работает, как и ожидалось.

import std.algorithm, std.array, std.stdio, std.string;

void main()
{
    stdin
        .byLineCopy
        .map!(strip)
        .array
        .sort!((a, b) => a.length < b.length)
        .each!writeln;
}

Однако, если я поменяю строку map на строку array,

void main()
{
    stdin
        .byLineCopy
        .array
        .map!(strip)
        .sort!((a, b) => a.length < b.length)
        .each!writeln;
}

Программа не скомпилируется со следующей ошибкой:

sort_lines.d(9): Error: template std.algorithm.sorting.sort cannot deduce function from argument types !((a, b) => a.length < b.length)(MapResult!(strip, string[])), candidates are:
/usr/include/dmd/phobos/std/algorithm/sorting.d(1852):        std.algorithm.sorting.sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if ((ss == SwapStrategy.unstable && (hasSwappableElements!Range || hasAssignableElements!Range) || ss != SwapStrategy.unstable && hasAssignableElements!Range) && isRandomAccessRange!Range && hasSlicing!Range && hasLength!Range)
Failed: ["/usr/bin/dmd", "-v", "-o-", "sort_lines.d", "-I."]

Я не могу понять, почему.Разве функция карты не применяется к каждому элементу в диапазоне и не возвращает новый диапазон?Согласно документации, sort требует, чтобы аргумент диапазона был произвольно доступен.Это причина?Если да, то какой тип диапазона возвращает map?

1 Ответ

0 голосов
/ 05 февраля 2019

map возвращает диапазон, в котором нет присваиваемых или заменяемых элементов - еще одно требование, указанное sort.Как и в первом примере, решение состоит в том, чтобы сначала выполнить итерацию в массиве.

Элементы не могут быть назначены, потому что map выполняет вычисления и не возвращает значение по ссылке ref.Таким образом, даже если вы захватите адрес возвращаемого элемента и перезапишите его новым значением для этой позиции, это не изменит значение в фактическом резервном массиве.

Проблема на самом деле немного хужечем это.[1,2,3].map!(a => a * 2) делает то, что он берет элемент из [1,2,3] и умножает его на 2. Если бы я сделал что-то вроде [1,2,3].map!(a => a * 2)[0] = 4, то пришлось бы инвертировать функцию a => a * 2, чтобы выяснить значение дляв [1,2,3], и превратить его в [2,2,3].В приведенном выше случае это относительно просто, но что, если я попытался назначить 5 вместо 4?Что, если функция отображения является односторонним хешем?Как мы видим, единственным реальным решением является магазин со значениями map ped - то есть [1,2,3].map.array.

...