Функции последовательностей из PABCSystem, реализованные повторным проходом по последовательности

Скажите, а как Вы собираетесь реализовывать Partition? У нас так:

function Partition<T>(Self: sequence of T; cond: T->boolean)
  : (sequence of T, sequence of T); extensionmethod;
begin
  Result := (Self.Where(cond), Self.Where(x -> not cond(x)));
end;

А Вы наверное списком:

function Partition<T>(Self: sequence of T; cond: T->boolean)
  : (sequence of T, sequence of T); extensionmethod;
begin
  var l := Self.ToList; // Второй проход по списку не страшен - побочного эффекта не будет
  Result := (l.Where(cond), l.Where(x -> not cond(x)));
end;

Или того хуже двумя?

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

(при этом temp это поле доп. класса который будет только в реализации PABCSystem, поэтому в программы он не будет попадать. Так же, через доп класс, реализованы большинство таких сложный функции из стандарта .Net )

Нет конечно, это ужасное решение. Потому что тут все элементы и обязательно придётся перенести в новый список. На самом деле в реализации всего подобного действует очень простая логика, надо думать что может понадобится в каждый момент и это и выдавать. Не знаю как полностью объяснить, но когда понял - становится очень просто.

Ещё раз - вы будете использовать список только для половины элементов (то есть для работы вашей функции будет требоваться O(n) памяти)?

И вы всерьёз считаете эту реализацию более эффективной?

Кстати, чтобы Вы быстро увидели - файл справки по blockFileOfT отображается так:

и гиперссылки не работают. Посмотрите, как оформляется кодировка в html.

Это только в худшем случае. Если дело будет касаться эффективности - можно считать сначала ту часть, которая скорее всего будет содержать больше элементов (по случаю это можно определить обычно).

И - в который раз говорю, дело не в эффективности, а в том что ни 1 из стандартных .Net функций не вычисляет последовательность >1 раза. И это вызовет непонятно поведение, у любого человека привыкшего к нормальную поведению функций последовательностей.

Всё же их >50 всего, а в PABCSystem таких очень мало, я вот умудрился только недавно наткнуться на них.

Сейчас попробую с гитхаба скачать, ибо у меня версия на компе норм. Но это вообще не в эту тему. Перенесите пожалуйста сюда.

P.S. кхм у меня и из Samples работает норм, ну сейчас действительно пойду посмотрю как кодировку устанавливать в html…

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

begin
  Writeln(ReadSeqInteger(25).Partition(t->t>0))
end.

Тут последовательность из 25 чисел придется вводить дважды. Это ужасно. Для всех подобных реализаций в Справке просто необходимо указать, что в случае использования расширений для последовательностей, вводимых с клавиатуры, данные придется перевводить. Выглядит какой-то капитуляцией перед реализацией: “извините, народ, мы пока что не смогли это сделать, как надо”.

Я уж не говорю о том, что будет, если отдать на вход последовательность от датчика случайных чисел.

1 лайк

Так и есть. Конвертируйте последовательность в массив для подобных применений. Последовательность не хранится в памяти - это её основное свойство. Кто этим не умеет пользоваться - плодят темы на форуме ))

Проблема-то в том, что неизвестно, для каких конвертировать, а для каких нет! Если для любых - то зачем вообще последовательности вводить с клавиатуры или получать от датчика случайных чисел? Надо тогда просто убрать эти возможности.

Вот вот и я про то. Ни для чего кроме этих 3 ваших функций не надо конвертировать. Поэтому логично ожидать что конвертирование не понадобится.

С вероятностью 50 процентов либо первая либо вторая.

Ещё раз - для ваших применений сконвертируйте вашу последовательность в список сразу во внешней программе - и делайте что хотите с ней. Память всё равно будет выделяться O(n), но побочных эффектов не будет

Я же говорю, если нужна очень прямо большая оптимизация - надо по случаю делать. А по случаю мож быть и не 50/50. То есть это уже от программиста использующего это зависит.

Но это для оптимизаций. А чтоб небыло нужны догадываться или делать .ToList после каждой операции над последовательностями - надо чтоб все функции последовательностей придерживались хоть каких про правил. .Net уже дало эти правила, так что изобретать ничего не надо.

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

Так что вы не одиноки в своём стремлении и даже не настолько круты.

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

Но пример, кстати, не в тему. Один проход по массиву всегда лучше чем несколько. Но 50 проходов по массиву лучше чем последовательности, хотя бы из за конструктора класса-наследника последовательности (который вызывается хотя бы раз для каждой функции). А для большинства функциий из .Net нужно хотя бы 2 конструктора.

Кстати, вы правы вот в чём.

В справке необходимо написать, что некоторые функции последовательностей будут неверно работать с мутируемыми последовательностями. Здесь я согласен.

В случае формирования последовательности на базе клавиатурного ввода или использования датчика случайных чисел к ней можно применять исключительно однопроходный алгоритм. Если то или иное расширение реализует многопроходный алгоритм, об этом пользователь обязан знать заранее. Иначе это просто подложенная ему бомба. Даже если у меня последовательность генерируется на основе какого-то итератора, я должен знать, не является ли алгоритм многопроходным. Это позволит мне самому решать, использовать ли последовательность или иную информационную структуру.

Неужели? Вот задача. Найти три первых минимума.

Категорически не согласен. Один из примеров Вам уже привели.

Такая последовательность мутируемая, а значит одноразовая. Если вы хотите сделать с ней что-то крутое, надо переводить её в массив и спокойно запускать несколько проходов.

Вообще странно, что для опытных программистов оказывается неочевидным факт, что по мутируемой последовательности второй проход даст другие результаты.

Ведь вы не сомневаетесь, что мутируемая функция Random() возвращает всякий раз разные значения и не отстаиваете то, чтобы она всегда возвращала одно и то же?

Совершенно неочевидно, что разделить последовательность на две по знаку элементов - это круто. Уже хотя бы потому, что чисто ручной алгоритм “берем очередной элемент и кидаем его либо направо, либо налево” не кажется чем-то выдающимся. Т.е. здесь как-то вот мутация этой последовательности не проглядывает. Или Вы под мутацией понимаете любую операцию, кроме фильтрации, проецирования и агрегирования?

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