Я узнал о продолжениях, читая Маленький Схемер Фридмана и Феллайзена, и, чтобы немного попрактиковаться с этой концепцией, я написал простой код, который, учитывая список целых чисел, удаляет четные числа и возвращает сумму шансы.
Это код моей схемы:
(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))
Я скомпилировал его по схеме курицы и работает, как и ожидалось, выдав результат 9.
Затем я попытался переписать тот же код на C ++, как показано ниже.
#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;
}
Попытка скомпилировать этот код с помощью g ++ 9.2.1 занимает очень много времени. Через несколько минут он израсходовал всю память моего ноутбука, и мне пришлось прервать сборку. Единственное предупреждение, которое я получаю от компилятора, связано, я думаю, только с использованием самого недавнего ключевого слова:
warning: use of ‘auto’ in parameter declaration only available with ‘-fconcepts’
7 | int rem_add(const std::set<int>& s, auto op) {
| ^~~~
Я хотел бы знать, что происходит под капотом: почему компилятор берет так много время и память для того, что выглядит как очень простой кусок кода?