# Recursion in lambda expressions

Alright, so I have two recursion functions with the exact same purpose:

``````let Fac = { n -> n == 0 ? 1 : n * Fac(n - 1) }

function! Fact(n)
return a:n == 0 ? 1 : a:n * Fact(a:n - 1)
endfunction
``````

While `Fact` works fine, recursive use of `Fac` seems to confuse vim:

``````:echo Fac(10)
Error detected while processing function <lambda>20:
line    1:
E117: Unknown function: Fac
-1
``````

Does lambda expression not support recursion, or did I call `Fac` in an incorrect way?

It is possible, but you must refer to Fac as a "global" with `g:` to allow the lambda to refer to "itself," even if it is not actually defined already.

``````let Fac = { n -> n == 0 ? 1 : n * g:Fac(n - 1) }
echo Fac(6)
``````

If we want to avoid global variables there are two issues:

1. Fac needs to be "dummy defined" for any closure to take effect.

2. At script level, the function is called s:Fac. Although it will work inside a function, with local variables.

It is possible to do this at script scope using `s:` as follows:

``````let s:Fac = { n -> 1 }
let s:Fac = { n -> n == 0  ? 1 : n * s:Fac(n - 1) }
echo s:Fac(6)
``````

Or at local function scope:

``````function DoSomething()
let Fac = { n -> 1 }
let Fac = { n -> n == 0 ? 1 : n * Fac(n - 1) }
echo Fac(6)
endfunction
call DoSomething()
``````

vim9script improves this situation somewhat, since it allows "declaring" variables by type annotation. It also works at script scope.

``````vim9script

var Fac: func(number): number
Fac = (n: number): number => {
return n == 0 ? 1 : n * Fac(n - 1)
}
``````
• What a bizarre behaviour... is it still possible to define `Fac` at the script level, or must I be declaring with `function` keyword? Commented Nov 4, 2022 at 10:40
• Yes, but for syntax reasons you must use `g:` or `s:` as follows: `let Fac = { n -> 1 } | let Fac = { n -> n == 0 ? 1 : n * g:Fac(n - 1) } | echo Fac(6) ` ~OR~ `let s:Fac = { n -> 1 } | let s:Fac = { n -> n == 0 ? 1 : n * s:Fac(n - 1) } | echo s:Fac(6) `
– Mass
Commented Nov 4, 2022 at 22:57
• Tested in ex mode, it looks like vim is comfortable even without the dummy in this way: `:echo Fac; E121: Undefined variable: Fac; :let Fac = { n -> n == 0 ? 1 : n * g:Fac(n - 1) }; :echo Fac(8); 40320` Commented Nov 5, 2022 at 10:16
• @Futarimiti, you're right this works because the function is global and has late binding. I have updated my answer accordingly.
– Mass
Commented Nov 6, 2022 at 2:55

I'm not sure if it's worth to do but, at least, it's worth to mention that we can also parse the call stack to get lambda's name. And so we have

``````" Calling the caller
function! Self(...) abort
return expand('<stack>')->split('[\d\+\]\.\.\|\s')[-2]->call(a:000)
endfunction

" will print 720
:echo call({ n -> n <= 1 ? 1 : n * Self(n - 1) }, [6])
``````
• Not exactly what I'm looking for but really innovative idea :) +1 Commented Nov 5, 2022 at 14:38