-*userfunc.txt* For Vim version 9.1. Last change: 2025 Oct 12
+*userfunc.txt* For Vim version 9.1. Last change: 2025 Oct 27
VIM REFERENCE MANUAL by Bram Moolenaar
No range is accepted. The function can be a partial with extra arguments, but
not with a dictionary. *E1300*
+In a |:def| function, a lambda can be used with |:defer|. Example: >
+
+ def Fn()
+ set lazyredraw
+ defer () => {
+ set lazyredraw&
+ }()
+ enddef
+<
==============================================================================
4. Automatically loading functions ~
int compile_arguments(char_u **arg, cctx_T *cctx, int *argcount, ca_special_T special_fn);
char_u *to_name_end(char_u *arg, int use_namespace);
char_u *to_name_const_end(char_u *arg);
+int compile_lambda(char_u **arg, cctx_T *cctx);
int get_lambda_tv_and_compile(char_u **arg, typval_T *rettv, int types_optional, evalarg_T *evalarg);
exprtype_T get_compare_type(char_u *p, int *len, int *type_is);
void skip_expr_cctx(char_u **arg, cctx_T *cctx);
v9.CheckSourceSuccess(lines)
enddef
+" Test for using defer with a lambda and a command block
+def Test_defer_lambda_func()
+ var lines =<< trim END
+ vim9script
+ var result = ''
+ def Foo()
+ result = 'xxx'
+ defer (a: number, b: string): number => {
+ result = $'{a}:{b}'
+ return 0
+ }(10, 'aaa')
+ result = 'yyy'
+ enddef
+ Foo()
+ assert_equal('10:aaa', result)
+ END
+ v9.CheckScriptSuccess(lines)
+
+ # Error: argument type mismatch
+ lines =<< trim END
+ vim9script
+ def Foo()
+ defer (a: number, b: string): number => {
+ return 0
+ }(10, 20)
+ enddef
+ defcompile
+ END
+ v9.CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected string but got number', 1)
+
+ # Error: not enough arguments
+ lines =<< trim END
+ vim9script
+ def Foo()
+ defer (a: number) => {
+ }()
+ enddef
+ defcompile
+ END
+ v9.CheckScriptFailure(lines, 'E119: Not enough arguments for function: (a: number) => {', 1)
+
+ # Error: too many arguments
+ lines =<< trim END
+ vim9script
+ def Foo()
+ defer () => {
+ }(10)
+ enddef
+ defcompile
+ END
+ v9.CheckScriptFailure(lines, 'E118: Too many arguments for function: () => {', 1)
+
+ # Error: invalid command in command-block
+ lines =<< trim END
+ vim9script
+ def Foo()
+ defer () => {
+ xxx
+ }()
+ enddef
+ defcompile
+ END
+ v9.CheckScriptFailure(lines, 'E476: Invalid command: xxx', 1)
+
+ # Error: missing return
+ lines =<< trim END
+ vim9script
+ def Foo()
+ defer (): number => {
+ }()
+ enddef
+ defcompile
+ END
+ v9.CheckScriptFailure(lines, 'E1027: Missing return statement', 1)
+
+ # Error: missing lambda body
+ lines =<< trim END
+ vim9script
+ def Foo()
+ defer (a: number): number
+ enddef
+ defcompile
+ END
+ v9.CheckScriptFailure(lines, 'E1028: Compiling :def function failed', 1)
+
+ # Error: invalid lambda syntax
+ lines =<< trim END
+ vim9script
+ def Foo()
+ defer (
+ enddef
+ defcompile
+ END
+ v9.CheckScriptFailure(lines, 'E1028: Compiling :def function failed', 1)
+enddef
+
" Test for using an non-existing type in a "for" statement.
def Test_invalid_type_in_for()
var lines =<< trim END
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1882,
/**/
1881,
/**/
int argcount = 0;
int defer_var_idx;
type_T *type = NULL;
- int func_idx;
+ int func_idx = -1;
- // Get a funcref for the function name.
- // TODO: better way to find the "(".
- paren = vim_strchr(arg, '(');
- if (paren == NULL)
+ if (*arg == '(')
{
- semsg(_(e_missing_parenthesis_str), arg);
- return NULL;
+ // a lambda function
+ if (compile_lambda(&arg, cctx) != OK)
+ return NULL;
+ paren = arg;
+ }
+ else
+ {
+ // Get a funcref for the function name.
+ // TODO: better way to find the "(".
+ paren = vim_strchr(arg, '(');
+ if (paren == NULL)
+ {
+ semsg(_(e_missing_parenthesis_str), arg);
+ return NULL;
+ }
+ *paren = NUL;
+ func_idx = find_internal_func(arg);
+ if (func_idx >= 0)
+ // TODO: better type
+ generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
+ &t_func_any, FALSE);
+ else if (compile_expr0(&arg, cctx) == FAIL)
+ return NULL;
+ *paren = '(';
}
- *paren = NUL;
- func_idx = find_internal_func(arg);
- if (func_idx >= 0)
- // TODO: better type
- generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
- &t_func_any, FALSE);
- else if (compile_expr0(&arg, cctx) == FAIL)
- return NULL;
- *paren = '(';
// check for function type
if (cctx->ctx_skip != SKIP_YES)
* "*arg" points to the '('.
* Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda.
*/
- static int
+ int
compile_lambda(char_u **arg, cctx_T *cctx)
{
int r;