Как стать автором
Обновить

Комментарии 19

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

Достаточно int64. При считывание символа на такт — его хватит на время больше существования вселенной.
Если считывать по миллиарду символов в секунду, хватит на примерно 8 млрд секунд (если int64 знаковый) — примерно 250 лет. Не так и много.
После чего выводится ответ 42
auto dist = std::distance(iota.begin(), iota.end());

Этот и тому подобный код перестанет быть криминальным, если
— сделать iota::iterator моделью random access iterator (что?! вы это ещё не сделали?! зря...)
— установить в качестве значения «недостижимой бесконечности» какое-нибудь очень большое число, например, iota::infinity = std::limits<ptrdiff_t>::max
— реализовать арифметику по модулю infinity (либо молиться, что мы не добежим до целочисленного переполнения — ни по нашему модулю, ни по машинному)
— и, если очень хочется, подправить операцию вычитания так, что distance(N,infinity) = infinity; впрочем, это уже необязательно

Если итераторы — честные forward, то можно сделать хак, чтобы distance по-быстрому проверяло, не является правый аргумент «бесконечностью».
Господа!
Приведите хотя бы один пример из реальности, где в реальных вычислениях требуются бесконечные интервалы… И вообще, в чем их глубокий вычислительный смысл-то ???
C++ особого смысла в них нет, т. к. нет вменяемых инструментов для работы с ними.
В том же Haskell бесконечные списки используются во всю — для индексации элементов другой последовательности, для построения конечных последовательностей с заданными свойствами (но для этого генераторы удобнее).
В хаскелле бесконечные списки — это генераторы, сделанные из удобного материала.
Будь то мап над йотой — т.е. [f x | x < — [1..]],
или итеративный процесс — iterate f x0 = [x0, f$x0, f$f$x0, ...],
или рекурсивные структуры — fibs = 0: 1: zipWith (+) fibs (tail fibs)

В С++ нет ленивых списков, соответственно, и выразительные средства другие.
Но те же итераторы (особенно из бустовского конструктора собери-сам) — вполне годная вещь, чтобы всякие групповые операции выражать через них.
Семантически да. Но человек работает с синтаксисом. В первом примере в генераторе вы всё равно использовали синтаксис списков. А как оно устроено внутри уже не важно (если опустить вопрос производительности), главное использовать удобно.

Хвостовая рекурсия, например, обычный цикл «из удобного материала». Но мы их различаем.
Кхм, кхм… это все понятно, я про другое, я спрашивал о бесконечности.
По вашим рассуждениям можно любой динамический контейнер назвать — бесконечным, хоть вектор, хоть список, хоть мап… в них нет ограничения на добавление.

Вот автор пишет:
— Необходимость бесконечных интервалов обосновать чуть сложнее.

А как по мне, то в C++ в них вообще смысла нет.
для контейнеров — vector, list и т.п…
для файлов, сокетов, портов… — потоки

Еще автор пишет:
— Представьте, что sin получает символы из сети, и этот код работает несколько дней, получая миллиарды символов.

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

Поэтому бесконечность в реальном мире — полная чушь. Я не понимаю, для чего нужны контейнеры, которые вместо своей длинны или итератора конца возвращают false.
Просто используйте while(true){std::cout << i++ << 'n';} — вот вам и вся бесконечность.
Зачем городить кучу мусорного кода для iota_range ??? В чем реальная польза этого класса? Очень хочется чтоб кто-нибудь привел пример его полезности в реалной жизни.
Я вам выше написал, что в C++ они не нужны.
А в Haskell нет прямого аналога while(true).
И я с Вами совершенно согласен, абсолютно непонятны мотивы и попытки автора реализации этой идеи на cpp.
«С++ тоже может». Статья чисто научно-развлекательного характера. Практической ценности она не предоставляет.
Кейс: получить первых N-штук, соответствующих условию F, из бесконечного генерируемого списка.
Ок :)
И как же должен выглядеть такой кейс с использованием беск.интервалов на сях? Я не совсем понимаю смысл фразы «из бесконечного генерируемого списка». В чем его плюс по сравнению с простым циклом и выходом по условию? Просто пример приведите…
Бесконечно генерируемый список используется в переборных алгоритмах: bruteforce пароля, выбор лучшего хода в игре, поиск лекарства от рака и т.д. При генерации используется расширяющийся список комбинаций. На первом этапе — все комбинации из одного элемента, на втором — комбинации из двух элементов и т.д.
Концепция «бесконечные интервалов» удобна для отделения генераторов от самого алгоритма перебора (цикла). Концепция «бесконечных интервалов» удобна при комбинировании генераторов.
С моей точки зрения их использование для этих целей не дает особого выигрыша ни в удобстве ни в производительности. Для комбинации генераторов достаточно в цикл передавать настраиваемый объект создающий комбинации для вызыва ф-ций генераторов по указателям.

Но спор наверно тут не имеет смысла, cpp позволяет решать одну задачу множеством вариантов, поэтому пусть каждый выбирает свой. Спасибо за более мене реальный пример применения.
1) Забег по файлу, особенно, по stdin
2) Поэлементные операции — std::transform, например, в двуместном случае считают, что второй диапазон если не бесконечен, то уж заведомо не короче первого.
3) Операции линейного поиска — если заведомо известно, что искомое значение встретится. Старая добрая strlen — это пример реального вычисления с бесконечным интервалом «от этой буквы и до упора».
Ещё учесть случай distance(infinity,N)
Там много чего можно учесть.
Но вообще, distance над перевёрнутым диапазоном forward-итераторов — это просто неопределённое поведение.

Проще всего это просечь и пресечь так: запретить инкремент (и декремент) infinity. Банальным ассертом.
Даже нет нужды делать арифметику с насыщением, infinity+k == infinity-k == infinity. Лишние проверки в релизном коде.
Нет уж! Бесконечность так бесконечность. Просто для её реализации мы похитим одно целое число из 4 миллиардов или 16 квадрильонов. Как когда-то авторы Си похитили адрес 0 для нулевого указателя (своеобразной минус-бесконечности).
Зарегистрируйтесь на Хабре, чтобы оставить комментарий