Cartesian : One example telling you why python is more readable than C++¶
By Rymoon, 2022/03/21 15:18
Wrote in Jupyter Notebook with xues-cling, C++17.
The Cartesian example is from C++17STL Cookbook.
Here is a very good example to show why Python scripts are more readable than C++ ones. Ths example is beyond the simple judgements like “runtime type”, but in aspect of that which language could express complex intentions more directly.
In [1]:
! gcc --version
gcc (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0 Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
First , I give out the algorithm in a Python script:
# cartesian.py
def call_cart(f,x,*rest):
for r in rest:
if x<r:
f(x,r)
def cartesian (*xs):
def _inner(f):
for x in xs:
call_cart(f,x,*xs)
return _inner
print_cart = cartesian(1,2,3)
# Print catesian to console
# Require the calling when imported
# To simulate the compiling time of C++
print_cart(print)
Next, a C++ version implemented by C++17 STL that prints cartesian pairs in compiling time.
With lambdas instead of templates, we could have things like auto f(auto x, auto ... x)
.
Variables and functions decorated by constexpr
are ran in compiling time.
In [2]:
#include <iostream>
void print(int x, int y){
std::cout << "(" <<x <<","<<y<<")\n";
}
In [3]:
{
constexpr auto call_cart (
[=](auto f, auto x, auto ...rest) constexpr {
(void) std::initializer_list<int>{
(((x<rest)
? (void)f(x,rest)
: (void) 0)
,0)...
};
});
constexpr auto cartesian ([=](auto ... xs) constexpr {
return [=](auto f)constexpr{
(void)std::initializer_list<int>{
((void)call_cart(f,xs,xs...),0)...
};
};
});
constexpr auto print_cart = (cartesian(1,2,3));
print_cart(print);
}
(1,2) (1,3) (2,3)
The following piece won’t work, with strange errors. So, use lambdas.
In [ ]:
#include <iostream>
template<typename F, typename X, typename... Rs>
auto call_cart(F f,X x, Rs ...rest){
std::initializer_list<int>{
((x<rest)?(void)f(x,rest):(void)0,0)...
};
}
/*
auto call_cart (
[=](auto f, auto x, auto ...rest) constexpr {
(void) std::initializer_list<int>{
(((x<rest)
? (void)f(x,rest)
: (void) 0)
,0)...
};
});
*/
template<typename... Xs>
auto cartesian(Xs... xs){
return [=](auto f){
std::initializer_list<int>{
((void)call_cart(f,xs,xs...),0)...
};
};
}
auto print_cart = (cartesian(1,2,3));
print_cart(print);
input_line_11:26:21: note: in instantiation of function template specialization 'cartesian<int, int, int>' requested here auto print_cart = (cartesian(1,2,3)); ^ input_line_11:27:1: error: unknown type name 'print_cart' print_cart(print); ^
In [ ]: