Как сгладить последовательность последовательностей на Цейлоне?

Учитывая тип, который является Последовательностью Последовательностей, как я могу преобразовать это в единственный, плоский тип Последовательности? Рассмотрим следующий код Цейлона:

Integer[] range(Integer max) {
    return [ for (idx in 1..max) idx ];
}

Integer[] prod(Integer max, Integer occurrences) {
    Integer[][] nestedSequence = [for (occurrence in 1..occurrences) range(max)];
    return // ??? something to produce a flattened sequence 
}

assert (prod(2, 2) == [1, 2, 1, 2]);

Я впервые экспериментирую с Цейлоном и пробираюсь по учебникам и документации API. Метод распаковки выглядит несколько близко к тому, что мне нужно, но не совсем так.

2 ответа

Решение

Вариадическая функция concatenate() объединяет итерации, создавая последовательность:

Integer[] prod(Integer max, Integer occurrences) {
    Integer[][] nestedSequence = [ for (occurrence in 1..occurrences) range(max) ];
    return concatenate(*nestedSequence);
}

Это может быть переписано менее подробно так:

Integer[] prod(Integer max, Integer occurrences)
        => concatenate(for (occurrence in 1..occurrences) range(max));

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

Integer[] prod4(Integer max, Integer occurrences)
        => [ for (occurrence in 1..occurrences) for (x in range(max)) x ];

К вашему сведению, на Цейлоне 1.1, expand() функция была добавлена, которая ленивее, чем concatenate(),

HTH, удачи!

Ваш range Функция здесь бесполезна, потому что она без необходимости создает последовательность вокруг диапазона. Вам просто нужно повторить от 1 в max, и вы можете сделать это непосредственно с диапазоном, созданным 1..max, Итак, замена range(max) с 1..maxВы можете определить prod как это:

Integer[] prod(Integer max, Integer occurrences)
        => (1..max).repeat(occurrences);

Чтобы ответить на ваш вопрос, при отсутствии concatenate а также expand как упоминалось в ответе Гэвина, вы можете получить уплощенную последовательность из nestedSequence с помощью Iterable.fold() как это:

nestedSequence.fold({}, ({Integer*} f, Integer[] r) => f.chain(r)).sequence;

Эквивалентное

Element[] flattened<Element>(Element[][] nestedSequence) {
    variable {Element*} flattened = {}; // same as f above
    for (Element[] range in nestedSequence) { // range is same as r above
        flattened = flattened.chain(range);
    }
    return flattened.sequence;
}

Но я предпочитаю последнюю реализацию Гэвина, используя понимания. Мне кажется, что Цейлон более идиоматичен по сравнению с fold,

Другие вопросы по тегам