Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
generator_example.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
56#include <cctype>
57#include <iostream>
58#include <stdexcept>
59#include <string>
60#include <vector>
61
62#include <ah-generator.H>
63#include <print_rule.H>
64
65using namespace Aleph;
66
67namespace
68{
69
70// An infinite sequence: 0, 1, 2, 3, ... forever. There is no eager
71// equivalent — you cannot materialize an infinite std::vector.
73{
74 for (long n = 0; ; ++n)
75 co_yield n;
76}
77
78void demo_laziness()
79{
80 std::cout << "[1] Laziness: an infinite sequence, truncated on demand\n";
81 print_rule();
82
83 std::cout << "First 5 multiples of 7, taken from an unbounded generator:\n";
84 long checked = 0;
85 long found = 0;
86 for (long n : natural_numbers())
87 {
88 ++checked;
89 if (n % 7 != 0)
90 continue;
91 std::cout << " " << n << "\n";
92 if (++found == 5)
93 break; // stops the coroutine outright; the rest is never produced
94 }
95 std::cout << "Candidates examined before stopping: " << checked << "\n";
96 std::cout << "The generator function never runs past that point — there is\n"
97 "no way to \"materialize\" natural_numbers() into a container.\n\n";
98}
99
100// True if `tok` is a full optional-sign, all-digits integer literal.
101bool is_plain_integer(const std::string &tok)
102{
103 if (tok.empty())
104 return false;
105 size_t i = (tok[0] == '+' or tok[0] == '-') ? 1 : 0;
106 if (i == tok.size())
107 return false;
108 for (; i < tok.size(); ++i)
109 if (not std::isdigit(static_cast<unsigned char>(tok[i])))
110 return false;
111 return true;
112}
113
114// A validating generator: parses each token to an int, and throws on the
115// first one that isn't a valid number instead of silently skipping it.
116//
117// `tokens` is taken BY VALUE on purpose, not by reference: a coroutine's
118// body doesn't run until the first resume (initial_suspend), so a
119// reference parameter bound to a caller's temporary (e.g.
120// `parse_ints({"10", "20"})`) would already be dangling by the time this
121// loop actually executes. Taking `tokens` by value sidesteps that pitfall
122// the same way `ah-comb-generators.H`'s `lazy_permutations`/
123// `lazy_combinations` do.
124Generator<int> parse_ints(std::vector<std::string> tokens)
125{
126 for (const std::string &tok : tokens)
127 {
129 << "not a valid integer: \"" << tok << "\"";
130 int value = std::stoi(tok);
131 co_yield value;
132 }
133}
134
136{
137 std::cout << "[2] Exception propagation across suspension points\n";
138 print_rule();
139
140 const std::vector<std::string> tokens = {"10", "20", "30", "oops", "40"};
141 std::cout << "Parsing tokens: 10, 20, 30, oops, 40\n";
142
143 int sum = 0;
144 try
145 {
146 for (int v : parse_ints(tokens))
147 {
148 std::cout << " parsed " << v << "\n";
149 sum += v;
150 }
151 }
152 catch (const std::invalid_argument &e)
153 {
154 std::cout << " caught: " << e.what() << "\n";
155 }
156 std::cout << "Sum of values parsed before the error: " << sum << " (expect 60)\n";
157 std::cout << "The three valid tokens were already consumed and summed; the\n"
158 "exception surfaced exactly where the fourth co_yield would\n"
159 "have been, just like a hand-written iterator would throw.\n\n";
160}
161
162// Two small composable stages, each a generator consuming another.
164{
165 for (long x : src)
166 if (x % 2 == 0)
167 co_yield x;
168}
169
171{
172 for (long x : src)
173 co_yield x * x;
174}
175
176void demo_composition()
177{
178 std::cout << "[3] Composition: chaining lazy stages\n";
179 print_rule();
180
181 std::cout << "squared(evens_only(natural_numbers())), first 6 values:\n";
182 int count = 0;
183 for (long v : squared(evens_only(natural_numbers())))
184 {
185 std::cout << " " << v << "\n";
186 if (++count == 6)
187 break;
188 }
189 std::cout << "Expect: 0, 4, 16, 36, 64, 100 — each stage only pulls as\n"
190 "many values from its source as the next stage asks for.\n\n";
191}
192} // namespace
193
194int main()
195{
196 std::cout << "\n=== Aleph::Generator<T>: lazy sequences ===\n\n";
197
201
202 std::cout << "Done.\n";
203 return 0;
204}
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:644
Lazy sequence type (Aleph::Generator<T>) built on C++20 coroutines.
size_t size_t int32_t value
Definition ca-c-api.h:116
Lazy, single-pass sequence of T values produced by a coroutine.
int main()
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
void print_rule()
Prints a horizontal rule for example output separation.
Definition print_rule.H:39
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.