Użyłem i przeczytałem o adnotacji @tailrec
, aby uzyskać metodę rekursywną ogona. Przeszedłem przez wiele linków, które to wyjaśniają. Na przykład działa tylko wtedy, gdy dla funkcji samodzielnego wywołania i nie powinien być nadpisywany itp.Jak działa @tailrec
Wszędzie wspomniano, że compiler optimizes
. Ale jaką magię/koncepcję robi kompilator, aby uczynić ją rekurencyjną. W przypadku prostej funkcji poniżej, co robi kompilator zrobić:
@tailrec def fact(acc: Int, n: Int): Int = {
if (n <= 1) acc
else fact(n * acc, n - 1)
}
fact(1,10)
Znaczy to przekształcić go w pętli, gdzie wielokrotnie nazywa go, a następnie zwraca wartość końcową? Czy istnieje jakiś związek do papieru, który wyjaśnia mu
Zasadniczo kompilator scala konwertuje kod na kod bajtowy podobny do pętli while. Prawdopodobnie robi coś takiego jak "var acc = 1; var n = 10; start: if (n <= 1) return acc else {acc = n * acc; n = n - 1; goto start} '. Powinno być możliwe mechaniczne zastąpienie wszystkich wywołań ogona za pomocą goto na początku ciała. – huynhjl