Próbuję napisać rekursję bez odwoływania się do nazwy funkcji w C++ za pomocą Y-combinator. Jednak nie mogę dowiedzieć się, rodzaj funkcji w następującej próbie:Czy jest możliwe utworzenie prawdziwego typu funkcji w C++, który można samodzielnie wywołać?
#include <iostream>
using std::cin;
using std::cout;
template<class Function> unsigned long factorial1(Function self, unsigned long n) {
return n ? n * self(self, n - 1) : 1;
}
unsigned long factorial(unsigned long n) {
return factorial1(factorial1, n);
}
int main() {
unsigned long n;
cin >> n;
cout << factorial(n) << '\n';
return 0;
}
Kompilator nie może wywnioskować co jest Function
, nie może mnie. Potem próbowałem następujące:
#include <iostream>
using std::cin;
using std::cout;
struct Factorial {
template<class Function> unsigned long operator()(Function self, unsigned long n) const {
return n ? n * self(self, n - 1) : 1;
}
};
unsigned long factorial(unsigned long n) {
return Factorial()(Factorial(), n);
}
int main() {
unsigned long n;
cin >> n;
cout << factorial(n) << '\n';
return 0;
}
ten, w porównaniu do powyższego przykładu, różnica jest taka, że zmienił funkcję pracy w na żądanie obiektu, który Function
jest wyprowadzona łatwo jak Factorial
, co prowadzi do następnego pełnego wdrożenia syntezatora:
#include <iostream>
using std::cin;
using std::cout;
struct Factorial {
template<class Function> unsigned long operator()(Function self, unsigned long n) const {
return n ? n * self(self, n - 1) : 1;
}
};
template<class Function> auto y(Function f) {
return [f](auto n) {
return f(f, n);
};
}
int main() {
unsigned long n;
cin >> n;
cout << y(Factorial())(n) << '\n';
return 0;
}
chodzi o to, że jest to możliwe do przerobienia struct Factorial
do zwykłej funkcji?
Patrząc na pierwszy przykład: Dlaczego nie chcesz odwoływać się do nazwy funkcji? Dlaczego "factorial1" jest szablonem? Co może "samo" kiedykolwiek być, jeśli nie "factorial1"? –
Kombinator Y potrzebuje silniejszego systemu typów (szablony zapewniają, jak sam odkryłeś, również pokazane [tutaj w Kodeksie Rosetty] (https://rosettacode.org/wiki/Y_combinator#C.2B.2B)) _or_ it potrzebuje systemu typu nnonexistent_ jak w rachunku bez lambda. Więc spróbuj użyć 'std :: uintptr_t' i odlewania w razie potrzeby ... (BTW: Brak gwarancji na ten komentarz.) – davidbak
ludzie odpowiedzieli na moje niepowiązane pytanie z y combinator: http://stackoverflow.com/questions/42796710/call -c-rekursywna-lambda-w-tej-linii-gdzie-to-jest-deklarowana – NoSenseEtAl