Функциональный Rust: Готовим говядину
Комментарии (4)
22 мая 2017 в 12:34
+1↑
↓
В Rust конечно же есть оптимизация хвостовой рекурсии, вот простейший пример (no_mangle исключительно для читаемости):0 ➜ cat a.rs #[no_mangle] pub fn test(a: i32) -> i32 { if a == 0 { 42 } else if a == 7 { 43 } else { test(a - 1) } } 0 ➜ rustc --crate-type dylib --emit llvm-ir -O a.rs
0 ➜ cat a.ll ; ModuleID = 'a.cgu-0.rs' source_filename = "a.cgu-0.rs" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" ; Function Attrs: nounwind readnone uwtable define i32 @test(i32) unnamed_addr #0 { start: br label %tailrecurse tailrecurse: ; preds = %bb4, %start %.tr = phi i32 [ %0, %start ], [ %1, %bb4 ] switch i32 %.tr, label %bb4 [ i32 0, label %bb7.loopexit i32 7, label %bb7.loopexit2 ] bb4: ; preds = %tailrecurse %1 = add i32 %.tr, -1 br label %tailrecurse bb7.loopexit2: ; preds = %tailrecurse br label %bb7 bb7.loopexit: ; preds = %tailrecurse br label %bb7 bb7: ; preds = %bb7.loopexit, %bb7.loopexit2 %_0.0 = phi i32 [ 43, %bb7.loopexit2 ], [ 42, %bb7.loopexit ] ret i32 %_0.0 } attributes #0 = { nounwind readnone uwtable }
Другое дело, что из вашего кода непонятно, то ли вы его неправильно написали, так как первоначальный вариант функции execute содержит точку с запятой в самом конце, что подразумевает, что последняя инструкция не новый execute (…), а просто (), пустая инструкция, такой код вообще по идее не должен скомпилироваться, потому что возвращаемое значение не совпадает с сигнатурой функции. То ли по какой-то иной причине не отработала оптимизация.
22 мая 2017 в 12:58
0↑
↓
Точка с запятой — это опечатка. Уже исправил.
Но вот этот кода то выдаёт stack overflow: click. Обьясните тогда, что же делать?
22 мая 2017 в 13:09
0↑
↓
Так, а где увас выход из рекурсии в примере?if i == 0 { 1 }
А из маин вы подаете count (1), таким образом мы не сможем выйти из рекурсии
22 мая 2017 в 13:15
0↑
↓
TCO, внезапно, нет и в Common Lisp (из-за динамических областей видимости, насколько я понимаю).