> Any idea what would be the best way to convert the snippet above?
Move the `i` variable in the script-local namespace. That is, don't declare it inside the function, but at the script-level. You can still reset it to a default value whenever the function is invoked:
vim9script
var i: number
def FixBeginfig()
i = 1
global /^beginfig(\d*);$/ substitute//\='beginfig(' .. i .. ');'/ | ++i
enddef
command -buffer -nargs=0 -bar FixBeginfigs FixBeginfig()
This works because – in a Vim9 script – all commands are executed in the Vim9 script context. As a result, they have access to any Vim9 syntax, and to all items defined in the script-local namespace.
Whether they're executed from a global command, an autocmd, a user command, a simple `:execute`, ... it doesn't matter.
For this reason, in your user command definition, you don't need `:call` nor `<sid>`. You don't need a bang after `:command` either since the patch v8.1.0573.
---
However, as mentioned earlier, there won't be a speed increase because the command is not compiled, just executed. Like most (all?) commands executed by another command. This is confirmed by the output of `:disassemble`:
<SNR>1_FixBeginfig
i = 1
0 PUSHNR 1
1 STORESCRIPT i-0 in /tmp/t.vim
global /^beginfig(\d*);$/ substitute//\='beginfig(' .. i .. ');'/ | ++i
2 EXEC global /^beginfig(\d*);$/ substitute//\='beginfig(' .. i .. ');'/ | ++i
3 RETURN void
Notice that the second generated instruction is a simple `EXEC`.
FWIW, I would still refactor the code in Vim9. Mainly because of type checking, and for better readability.