Today, I finish my experiment writing beloved Python functions in C++. So far, I have implemented the Python functions filter, range, and xrange. Today, I have a closer look at the map function and combine the functions map and filter into one function.
It was implemented in my last post, “C++20: Pythons range Function, the Second” a lazy variant of range: xrange. A few of my German readers complain that xrange does not behave, such as Python 2 xrange function. My xrange function requires constant expressions for the created numbers’ beginning and end.
In the example, 1 and 10 are constant expressions. This means an expression such as the following one would not compile.
I assume you know what that means?
Pythons range Function, the Third
Thanks to my German reader Clocktown, I can present the final version of xrange. The function xrange is lazy and can also accept arguments for the boundaries, which are not constant expressions.
The key idea of his implementation is that view::transform eventually transforms the calculation into a reverse variant. xrange can be invoked with one, two, or three arguments. The default for the first argument is 0, and for the third argument is 1. Let’s try it out. I replaced the xrange implementation of my last post with this new implementation.
As expected, I got the same result.
So far, nothing new. But here are the new use cases. begin and end are not constant expressions, and xrange supports one argument.
Now, I’m done with the function range and xrange. Let me continue with the function map.
First, here is my simplified definition of Pythons 2 map function. I restrict map to one sequence
- map(function, sequence): Returns a list by applying the function to each input sequence element.
If you think about it, there is one challenge to overcome. In contrast to Pythons function filter (C++20: Pythonic with the Ranges Library), map can change the type of the input sequence.
Line (4) deduces the return_type. The return_type is the type to which all input sequence elements are transformed if the function func is applied to them. std::declval<value_type>() returns a rvalue reference which can be used by decltype to deduce the type.
The commented-out lines are the corresponding Python code.
- maps each element to its square
- maps each word to a pair length of the word, and the word
- Reads each line from the file “/etc/services“, maps each line to the pair length of the line and the line, sorts the resulting sequence in reverse order, and displays the 3 longest lines.
The screenshot shows the output of the program.
I almost forgot to mention another issue I had to implement the map function. The call std::vector words = text | ranges::views::split(‘\n’); (line 4) is deprecated. Instead, I should use the conversion operator ranges::to. ranges::to is not part of C++20, so I asked the author of the ranges library, Eric Niebler, what I should do. He proposed a quite wordy solution that triggered a GCC bug. Here is the bug report 93936 from Eric. Finally, I stick to the deprecated version.
The function map is not the end of my experiments. I said to myself. Let’s combine map and filter into one function and create something similar to list comprehension in C++. Honestly, I’m not 100% satisfied with the result.
A flavor of list comprehension
My function mapFilter can only handle one sequence in contrast to list comprehension in Python.
The default predicate that the filter function applies (line 2) consistently returns true (line 1). Always true means that the function mapFilter behaves per default, such as the map function. When you study all lines numbered (3), you see no difference to the previous program map.cpp. But now, the difference begins. The corresponding list comprehensions in Python are commented out.
- Line (4) calculates the square of the odd numbers.
- Line (5) returns pairs (length of the word, word) if the word starts with a capital character.
- Line (6) returns a vector of all lines of the file “/etc/services“, which have between 100 and 150 characters.
This post was a little longer than usual. My next post is about generalized functions that can be paused and resumed. To make it short: my next post is about coroutines.
Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, and Bhavith C Achar.
Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.
|My special thanks to Embarcadero|
|My special thanks to PVS-Studio|
|My special thanks to Tipi.build|
|My special thanks to Take Up Code|
I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
- Embedded Programmierung mit modernem C++ 12.12.2023 – 14.12.2023 (Präsenzschulung, Termingarantie)
Standard Seminars (English/German)
Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.
- C++ – The Core Language
- C++ – The Standard Library
- C++ – Compact
- C++11 and C++14
- Concurrency with Modern C++
- Design Pattern and Architectural Pattern with C++
- Embedded Programming with Modern C++
- Generic Programming (Templates) with C++
- Clean Code with Modern C++
- Phone: +49 7472 917441
- Mobil:: +49 176 5506 5086
- Mail: schulung@ModernesCpp.de
- German Seminar Page: www.ModernesCpp.de
- Mentoring Page: www.ModernesCpp.org
Modernes C++ Mentoring,