{"id":5857,"date":"2020-02-27T09:14:39","date_gmt":"2020-02-27T09:14:39","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-20-pythonic-with-the-ranges-library\/"},"modified":"2023-09-27T16:54:46","modified_gmt":"2023-09-27T16:54:46","slug":"c-20-pythonic-with-the-ranges-library","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-20-pythonic-with-the-ranges-library\/","title":{"rendered":"C++20: Pythonic with the Ranges Library"},"content":{"rendered":"<p>Today, I start an experiment. I want to implement beloved functions in Python in C++ using the ranges library. I&#8217;m curious about how it goes.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-8380 size-full\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges.png\" alt=\"\" width=\"979\" height=\"373\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges.png 979w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges-300x114.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges-768x293.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges-705x269.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges-845x321.png 845w\" sizes=\"auto, (max-width: 979px) 100vw, 979px\" \/><\/p>\n<p>You maybe know it. I&#8217;m also a Python trainer since 2004. Python has excellent functions, and often Python is, for me, the threshold of how comfortable a programming language could be. Today, I want to implement the Python functions <span style=\"font-family: courier new, courier;\">range<\/span> and <span style=\"font-family: courier new, courier;\">filter<\/span>.<\/p>\n<ul>\n<li><span style=\"font-family: courier new, courier;\">range<\/span> creates a list &#8220;containing an arithmetic progression of integers&#8221; (Python built-in help).<\/li>\n<li><span style=\"font-family: courier new, courier;\">filter<\/span> applies a predicate to a sequence and returns those elements for which the predicate returns true.<\/li>\n<\/ul>\n<p>A sequence is a term in Python that stands for something iterable such as a <span style=\"font-family: courier new, courier;\">list<\/span> (<span style=\"font-family: courier new, courier;\">[1, 2, 3]<\/span>), a <span style=\"font-family: courier new, courier;\">tuple<\/span> (<span style=\"font-family: courier new, courier;\">(1, 2, 3)<\/span>), or a <span style=\"font-family: courier new, courier;\">string<\/span> (<span style=\"font-family: courier new, courier;\">&#8220;123&#8221;<\/span>). Instead of a <span style=\"font-family: courier new, courier;\">list<\/span>, I use a <span style=\"font-family: courier new, courier;\">std::vector<\/span> in C++. The functions <span style=\"font-family: courier new, courier;\">filter <\/span>stands for the functional style in Python.<\/p>\n<p>Before I start with the <span style=\"font-family: courier new, courier;\">range<\/span> function, I have to make a few remarks.<\/p>\n<ol>\n<li>I use in my examples the<a href=\"https:\/\/github.com\/ericniebler\/range-v3\"> range-v3<\/a> library from Eric Niebler, which is the basis for the C++20 ranges. I showed in my previous post, <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-20-the-ranges-library\">C++20: The Ranges Library<\/a>, how to translate the ranges-v3 to the C++20 syntax.<\/li>\n<li>Python code is often shorter than C++ Code for two reasons. First, I don&#8217;t store the Python lists in a variable, and second, I don&#8217;t display the result.<\/li>\n<li>I don&#8217;t like religious wars about programming languages. The middle-aged are long gone. I will not react to these comments.<\/li>\n<\/ol>\n<p>Let&#8217;s start with the <span style=\"font-family: courier new, courier;\">range<\/span> function. The <span style=\"font-family: courier new, courier;\">range<\/span> function is a kind of building block for creating integers.<\/p>\n<h2><span style=\"font-family: courier new, courier;\">range<\/span><\/h2>\n<p>In the following examples, I first show the Python expression commented out and then the corresponding C++ call.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555;\">\/\/<\/span> <span style=\"color: #336666;\">range<\/span><span style=\"color: #555555;\">.<\/span>cpp\n\n<span style=\"color: #0099ff; font-style: italic;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">#include &lt;range\/v3\/all.hpp&gt;<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">#include &lt;vector&gt;<\/span>\n\nstd::vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #336666;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #336666;\">int<\/span> begin, <span style=\"color: #336666;\">int<\/span> end, <span style=\"color: #336666;\">int<\/span> stepsize <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>) {\n    std::vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #336666;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> result{};\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (begin <span style=\"color: #555555;\">&lt;<\/span> end) {                                     <span style=\"color: #555555;\">\/\/<\/span> (<span style=\"color: #ff6600;\">5<\/span>)\n        auto boundary <span style=\"color: #555555;\">=<\/span> [end](<span style=\"color: #336666;\">int<\/span> i){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> i <span style=\"color: #555555;\">&lt;<\/span> end; };\n        <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #336666;\">int<\/span> i: ranges::views::iota(begin) <span style=\"color: #555555;\">|<\/span> ranges::views::stride(stepsize) \n                                               <span style=\"color: #555555;\">|<\/span> ranges::views::take_while(boundary)) {\n            result<span style=\"color: #555555;\">.<\/span>push_back(i);\n        }\n    }\n    <span style=\"color: #006699; font-weight: bold;\">else<\/span> {                                                 <span style=\"color: #555555;\">\/\/<\/span> (<span style=\"color: #ff6600;\">6<\/span>)\n        begin<span style=\"color: #555555;\">++<\/span>;\n        end<span style=\"color: #555555;\">++<\/span>;\n        stepsize <span style=\"color: #555555;\">*=<\/span> <span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">1<\/span>;\n        auto boundary <span style=\"color: #555555;\">=<\/span> [begin](<span style=\"color: #336666;\">int<\/span> i){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> i <span style=\"color: #555555;\">&lt;<\/span> begin; };\n        <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #336666;\">int<\/span> i: ranges::views::iota(end) <span style=\"color: #555555;\">|<\/span> ranges::views::take_while(boundary) \n                                             <span style=\"color: #555555;\">|<\/span> ranges::views::reverse \n                                             <span style=\"color: #555555;\">|<\/span> ranges::views::stride(stepsize)) {\n            result<span style=\"color: #555555;\">.<\/span>push_back(i);\n        }\n    }\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> result;\n}\n        \n<span style=\"color: #336666;\">int<\/span> main() {\n    \n    std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std::endl;\n\n    <span style=\"color: #555555;\">\/\/<\/span> <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">50<\/span>)                                       <span style=\"color: #555555;\">\/\/<\/span> (<span style=\"color: #ff6600;\">1<\/span>)\n    auto res <span style=\"color: #555555;\">=<\/span> <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">50<\/span>);\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (auto i: res) std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> i <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;\n    \n    std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\n    \n    <span style=\"color: #555555;\">\/\/<\/span> <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">50<\/span>, <span style=\"color: #ff6600;\">5<\/span>)                                    <span style=\"color: #555555;\">\/\/<\/span> (<span style=\"color: #ff6600;\">2<\/span>)\n    res <span style=\"color: #555555;\">=<\/span> <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">50<\/span>, <span style=\"color: #ff6600;\">5<\/span>);\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (auto i: res) std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> i <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;\n    \n    std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\n    \n    <span style=\"color: #555555;\">\/\/<\/span> <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">50<\/span>, <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">1<\/span>)                                  <span style=\"color: #555555;\">\/\/<\/span> (<span style=\"color: #ff6600;\">3<\/span>)\n    res <span style=\"color: #555555;\">=<\/span> <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">50<\/span>, <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">1<\/span>);\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (auto i: res) std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> i <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;\n    \n    std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\n    \n    <span style=\"color: #555555;\">\/\/<\/span> <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">50<\/span>, <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">5<\/span>)                                  <span style=\"color: #555555;\">\/\/<\/span> (<span style=\"color: #ff6600;\">4<\/span>)\n    res <span style=\"color: #555555;\">=<\/span> <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">50<\/span>, <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">5<\/span>);\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (auto i: res) std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> i <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;\n    \n    std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\n    \n}\n<\/pre>\n<\/div>\n<p>The calls in lines (1) &#8211; (4) should be quite easy to read when you look at the output.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5855\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/range.png\" alt=\"range\" width=\"650\" height=\"279\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/range.png 884w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/range-300x129.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/range-768x330.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>The first two arguments of the range call stand for the beginning and end of the created integers. The beginning is included but not the end. Step size as the third parameter is per default 1. When the interval [begin, end[ is decreasing, the step size should be negative. If not, you get an empty <span style=\"font-family: courier new, courier;\">list<\/span> or <span style=\"font-family: courier new, courier;\">std::vector&lt;int&gt;<\/span>.<\/p>\n<p>I cheat a little in my range implementation. I use the function <span style=\"font-family: courier new, courier;\">ranges::views::stride<\/span> which is not part of C++20. <span style=\"font-family: courier new, courier;\">stride(n)<\/span> returns the n-th element of the given range. If you know an elegant implementation based on C++20, please let me know.<\/p>\n<p>The if condition (<span style=\"font-family: courier new, courier;\">begin &lt; end<\/span>) of the range function in line (1) should be quite easy to read. Create all numbers starting with begin (<span style=\"font-family: courier new, courier;\">ranges::views::iota(begin)),<\/span> take each n-th element (<span style=\"font-family: courier new, courier;\">ranges::views::stride(stepsize<\/span>), and do it as long as the boundary condition holds (<span style=\"font-family: courier new, courier;\">ranges::views::take_while(boundar<\/span>y). Finally, push the integers on the <span style=\"font-family: courier new, courier;\">std::vector&lt;int&gt;. <\/span><\/p>\n<p>I use a little trick in the other case (line 2). I create the numbers <span style=\"font-family: courier new, courier;\">[end++, begin++[,<\/span> take them until the boundary condition is met, reverse them (<span style=\"font-family: courier new, courier;\">ranges::views::reverse<\/span>), and take each n-th element.<\/p>\n<p>I implement the eager version for <span style=\"font-family: courier new, courier;\">filter<\/span> and <span style=\"font-family: courier new, courier;\">map<\/span> (next post) in my examples. With Python 3 <span style=\"font-family: courier new, courier;\">filter<\/span> and <span style=\"font-family: courier new, courier;\">map<\/span> are lazy. <span style=\"font-family: 'courier new', courier;\">filter<\/span> and <span style=\"font-family: 'courier new', courier;\">map<\/span> return, in this case, generators. To get the eager behavior of Python 2, put a <span style=\"font-family: courier new, courier;\">list<\/span> around the <span style=\"font-family: courier new, courier;\">filter<\/span> and <span style=\"font-family: courier new, courier;\">map<\/span> calls in Python 3.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #336666;\">filter<\/span>(<span style=\"color: #006699; font-weight: bold;\">lambda<\/span> i: (i % 2) == 1 , <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">10<\/span>))       <span style=\"color: #0099ff; font-style: italic;\"># Python 2   <\/span>\n\n<span style=\"color: #336666;\">list<\/span>(<span style=\"color: #336666;\">filter<\/span>(<span style=\"color: #006699; font-weight: bold;\">lambda<\/span> i: (i % 2) == 1, <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">10<\/span>))) <span style=\"color: #0099ff; font-style: italic;\"># Python 3<\/span>\n<\/pre>\n<\/div>\n<p>Both calls produce the same list: <span style=\"font-family: courier new, courier;\">[1, 3, 5, 7, 9<\/span>].<\/p>\n<p>I continue with the function <span style=\"font-family: courier new, courier;\">filter<\/span> because it is easier to implement, such as the map function.<\/p>\n<h2><span style=\"font-family: courier new, courier;\">filter<\/span><\/h2>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555;\">\/\/<\/span> <span style=\"color: #336666;\">filter<\/span><span style=\"color: #555555;\">.<\/span>cpp\n\n<span style=\"color: #0099ff; font-style: italic;\">#include \"range.hpp\"                          \/\/ (1)<\/span>\n\n<span style=\"color: #0099ff; font-style: italic;\">#include &lt;fstream&gt;<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">#include &lt;range\/v3\/all.hpp&gt;\n#include &lt;sstream&gt;<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">#include &lt;string&gt;<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">#include &lt;vector&gt;<\/span>\n<span style=\"color: #0099ff; font-style: italic;\">#include &lt;utility&gt;<\/span>\n\ntemplate <span style=\"color: #555555;\">&lt;<\/span>typename Func, typename Seq<span style=\"color: #555555;\">&gt;       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span><\/span>\nauto <span style=\"color: #336666;\">filter<\/span>(Func func, Seq seq) {\n    \n    typedef typename Seq::value_type value_type;\n\n    std::vector<span style=\"color: #555555;\">&lt;<\/span>value_type<span style=\"color: #555555;\">&gt;<\/span> result{};\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (auto i : seq <span style=\"color: #555555;\">|<\/span> ranges::views::<span style=\"color: #336666;\">filter<\/span>(func)) result<span style=\"color: #555555;\">.<\/span>push_back(i);\n    \n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> result;\n}\n\n\n<span style=\"color: #336666;\">int<\/span> main() {\n    \n    std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std::endl;\n    \n    <span style=\"color: #555555;\">\/\/<\/span> <span style=\"color: #336666;\">filter<\/span>(<span style=\"color: #006699; font-weight: bold;\">lambda<\/span> i: (i <span style=\"color: #555555;\">%<\/span> <span style=\"color: #ff6600;\">3<\/span>) <span style=\"color: #555555;\">==<\/span> <span style=\"color: #ff6600;\">0<\/span> , <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">20<\/span>, <span style=\"color: #ff6600;\">50<\/span>))     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\n    auto res <span style=\"color: #555555;\">=<\/span> <span style=\"color: #336666;\">filter<\/span>([](<span style=\"color: #336666;\">int<\/span> i){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> (i <span style=\"color: #555555;\">%<\/span> <span style=\"color: #ff6600;\">3<\/span>) <span style=\"color: #555555;\">==<\/span> <span style=\"color: #ff6600;\">0<\/span>; }, <span style=\"color: #336666;\">range<\/span>(<span style=\"color: #ff6600;\">20<\/span>, <span style=\"color: #ff6600;\">50<\/span>) );\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (auto v: res) std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> v <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;\n    \n                                                          <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span> \n    <span style=\"color: #555555;\">\/\/<\/span> <span style=\"color: #336666;\">filter<\/span>(<span style=\"color: #006699; font-weight: bold;\">lambda<\/span> word: word[<span style=\"color: #ff6600;\">0<\/span>]<span style=\"color: #555555;\">.<\/span>isupper(), [<span style=\"color: #cc3300;\">\"Only\"<\/span>, <span style=\"color: #cc3300;\">\"for\"<\/span>, <span style=\"color: #cc3300;\">\"testing\"<\/span>, <span style=\"color: #cc3300;\">\"purpose\"<\/span>]) \n    std::vector<span style=\"color: #555555;\">&lt;<\/span>std::string<span style=\"color: #555555;\">&gt;<\/span> myStrings{<span style=\"color: #cc3300;\">\"Only\"<\/span>, <span style=\"color: #cc3300;\">\"for\"<\/span>, <span style=\"color: #cc3300;\">\"testing\"<\/span>, <span style=\"color: #cc3300;\">\"purpose\"<\/span>};\n    auto res2 <span style=\"color: #555555;\">=<\/span> <span style=\"color: #336666;\">filter<\/span>([](const std::string<span style=\"color: #555555;\">&amp;<\/span> s){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> static_cast<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #336666;\">bool<\/span><span style=\"color: #555555;\">&gt;<\/span>(std::isupper(s[<span style=\"color: #ff6600;\">0<\/span>])); }, myStrings);\n     \n    std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\n     \n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (auto word: res2) std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> word <span style=\"color: #555555;\">&lt;&lt;<\/span> std::endl;\n    \n    std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std::endl;\n                                                        \n                                                          <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\n    <span style=\"color: #555555;\">\/\/<\/span> <span style=\"color: #336666;\">len<\/span>(<span style=\"color: #336666;\">filter<\/span>(<span style=\"color: #006699; font-weight: bold;\">lambda<\/span> line: line[<span style=\"color: #ff6600;\">0<\/span>] <span style=\"color: #555555;\">==<\/span> <span style=\"color: #cc3300;\">\"#\"<\/span>, <span style=\"color: #336666;\">open<\/span>(<span style=\"color: #cc3300;\">\"\/etc\/services\"<\/span>)<span style=\"color: #555555;\">.<\/span>readlines()))\n    std::ifstream <span style=\"color: #336666;\">file<\/span>(<span style=\"color: #cc3300;\">\"\/etc\/services\"<\/span>, std::ios::<span style=\"color: #000000; font-weight: bold;\">in<\/span>);\n    std::vector lines;\n    std::string line;\n    while(std::getline(file, line)){\n        lines.push_back(line);\n    }\n    std::vector<span style=\"color: #555555;\">&lt;<\/span>std::string<span style=\"color: #555555;\">&gt;<\/span> commentLines <span style=\"color: #555555;\">=<\/span> <span style=\"color: #336666;\">filter<\/span>([](const std::string<span style=\"color: #555555;\">&amp;<\/span> s){  <span style=\"color: #006699; font-weight: bold;\">return<\/span> s[<span style=\"color: #ff6600;\">0<\/span>] <span style=\"color: #555555;\">==<\/span> <span style=\"color: #cc3300;\">'#'<\/span>; }, lines);\n    \n    std::cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Comment lines: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> commentLines<span style=\"color: #555555;\">.<\/span>size() <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\n                                          \n}\n<\/pre>\n<\/div>\n<p>Before I explain the program, let me show you the output.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5856\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/filter.png\" alt=\"filter\" width=\"350\" height=\"280\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/filter.png 377w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/filter-300x240.png 300w\" sizes=\"auto, (max-width: 350px) 100vw, 350px\" \/><\/p>\n<p>This time, I include the range implementation from before. The <span style=\"font-family: courier new, courier;\">filter<\/span> function (line 2) should be easy to read. I apply the callable <span style=\"font-family: courier new, courier;\">func<\/span> to each sequence element and materialize the elements in the<span style=\"font-family: courier new, courier;\"> std::vector.<\/span> Line (3) creates all numbers i from 20 to 50 for which hold (i % 3) == 0. Only the strings that start with an uppercase letter can pass the filter inline (4). Line (5) counts how many lines in the file &#8220;<span style=\"font-family: courier new, courier;\">\/etc\/services<\/span>&#8221; are comments. Comments are lines that start with the<span style=\"font-family: courier new, courier;\"> &#8216;#&#8217;<\/span> character.<\/p>\n<p>If you ignore the different ways to implement lambdas in Python and C++, the <span style=\"font-family: courier new, courier;\">filter<\/span> calls are quite similar.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>map was way more complicated to implement than <span style=\"font-family: courier new, courier;\">filter.<\/span> First, <span style=\"font-family: courier new, courier;\">map<\/span> may change the type of the input sequence. Second, my implementation of <span style=\"font-family: courier new, courier;\">map<\/span> triggered a GCC bug report. Afterward, I combine the functions <span style=\"font-family: courier new, courier;\">map<\/span> and <span style=\"font-family: courier new, courier;\">filter<\/span> in a function and I get &#8230; . Read the details in my <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-20-more-pythonic-with-the-ranges-library\">next post<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today, I start an experiment. I want to implement beloved functions in Python in C++ using the ranges library. I&#8217;m curious about how it goes.<\/p>\n","protected":false},"author":21,"featured_media":8380,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[412,413],"class_list":["post-5857","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-python","tag-ranges"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5857","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5857"}],"version-history":[{"count":2,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5857\/revisions"}],"predecessor-version":[{"id":8390,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5857\/revisions\/8390"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/8380"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5857"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5857"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5857"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}