I discovered about continuations while reading The Little Schemer by Friedman and Felleisen, and to practice a little with this concept I wrote a simple code that given a list of integers removes the evens and returns the sum of the odds.
This is my scheme code:
(define nil '())
; s is a list of integers, op is an operator.
(define (rem_add s op)
(cond ((null? s) (op nil 0))
((even? (car s))
(rem_add (cdr s)
(lambda (l n) (op l n))))
(else
(rem_add (cdr s)
(lambda (l n) (op (cons (car s) l) (+ n 1)))))))
(define (count s n)
(cond ((null? s) 0)
(else (+ (car s) (count (cdr s) n)))))
(define s (list 1 2 3 4 5))
(display (rem_add s count))
I compiled it with chicken scheme and works as expected, producing the output 9.
Then I tried to rewrite the same code in C++, as follows.
#include<functional>
#include<iostream>
#include<set>
int rem_add(const std::set<int>& s, auto op) {
if (s.empty()) {
return op(s, 0);
}
std::set<int> s2(++s.cbegin(), s.cend());
if (*s.cbegin() % 2 == 0) {
return rem_add(s2,
[op](const std::set<int>& l, int n){
return op(l, n);
});
} else {
return rem_add(s2,
[&s, op](const std::set<int>& l, int n){
std::set<int> q(l);
q.insert(*s.cbegin());
return op(q, n + 1);
});
}
}
// Remove the even elements from s, and return the sum of the odd elements.
int main() {
std::set<int> s {1, 2, 3, 4, 5};
std::function<int(const std::set<int>&, int)>
count = [count](const std::set<int>& s, int n)
{ if (s.empty()) { return 0; }
std::set<int> s2(++s.cbegin(), s.cend());
return *s.cbegin() + count(s2, n);
};
auto sum_odds = rem_add(s, count);
std::cout << sum_odds << std::endl;
}
Trying to compile this code with g++ 9.2.1 takes very long. After a few minutes it used up all the memory of my laptop and I had to abort the compilation. The only compiler warning I get is related, I think, just to the use of a very recent keyword:
warning: use of ‘auto’ in parameter declaration only available with ‘-fconcepts’
7 | int rem_add(const std::set<int>& s, auto op) {
| ^~~~
I would like to know what is happening under the hood: why does the compiler take so much time and memory for what looks like a very simple piece of code?