You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
3.1 KiB

2 years ago
function! Foo()
let x = 0
function! Bar() closure
let x += 1
return x
endfunction
return funcref('Bar')
endfunction
function! Goo()
let x = 0
function! Bar() closure
let x += 2
return x
endfunction
return function('Bar')
endfunction
" funcref 与 function 都有效
" Bar() 也是全局函数
echo 'Fn = Foo()'
let Fn = Foo()
echo Fn()
echo Fn()
echo Bar()
echo Fn()
" 交替使用有效
echo 'Gn = Foo()'
let Gn = Goo()
echo Gn()
echo Gn()
echo Bar()
echo Gn()
function! Bar()
return 'Bar() redefined'
endfunction
echo Bar()
echo Fn()
echo Gn()
"
" 重定义对 function() 有影响,对 funcref() 影响
" 对比 s: 变量与函数
"
let s:x = 0
function! s:Bar() " closure 不能放在顶层 E932
let s:x += 1
return s:x
endfunction
echo 's:Bar()'
echo s:Bar()
echo s:Bar()
echo s:Bar()
" 工厂函数
" 闭包独立性
"
function! FGoo(base)
let x = a:base
function! Bar1_cf() closure
let x += 1
return x
endfunction
function! Bar2_cf() closure
let x += 2
return x
endfunction
return [funcref('Bar1_cf'), funcref('Bar2_cf')]
endfunction
echo 'FGoo(base)'
let [Fn, X_] = FGoo(10)
echo Fn()
echo Fn()
echo Fn()
let [X_, Gn] = FGoo(20)
echo Gn()
echo Gn()
echo Gn()
echo Fn()
echo Fn()
" 偏包引用
"
echo 'partial function reference'
function! Full(x, y, z)
echo 'Full called:' a:x a:y a:z
endfunction
let Part = function('Full', [3, 4])
call Part(5)
echo Part
" call Part()
" call Part(3, 4, 5)
function! FullPartial()
let x = 3
let y = 4
function! Part_cf(z) closure
let z = a:z
return Full(x, y, z)
endfunction
return funcref('Part_cf')
endfunction
let Part = FullPartial()
call Part(5)
echo Part
function! FuncPartial(fun, arg)
" let l:arg_closure = a:arg
function! Part_cf(...) closure
" let l:arg_passing = a:000
" let l:arg_all = l:arg_closure + l:arg_passing
return call(a:fun, a:arg + a:000)
endfunction
return funcref('Part_cf')
endfunction
let Part = FuncPartial('Full', [3, 4])
call Part(5)
echo Part
" lambda 表达式
"
echo 'lambda expression'
if 1
function! Distance(point) abort
let x = a:point[0]
let y = a:point[1]
return x*x + y*y
endfunction
else
let Distance = {pt -> pt[0] * pt[0] + pt[1] * pt[1]}
endif
" echo Distance
echo Distance([3,4])
function! MaxDistance(A, B, C) abort
let l:Distance = {pt -> pt[0] * pt[0] + pt[1] * pt[1]}
let [A, B, C] = [a:A, a:B, a:C]
let e1 = [A[0] - B[0], A[1] - B[1]]
let e2 = [A[0] - C[0], A[1] - C[1]]
let e3 = [B[0] - C[0], B[1] - C[1]]
let d1 = Distance(e1)
let d2 = l:Distance(e2)
let d3 = Distance(e3)
if d1 >= d2 && d1 >= d3
return d1
elseif d2 >= d1 && d2 >= d3
return d2
else
return d3
endif
endfunction
delfunction Distance
echo MaxDistance([2,8], [4,4], [5,10])
finish
"
" 在 MaxDistance 中调用 Distance lambda 时,须定义为局部函数引用变量
" 因 Distance() 调用只搜索 l:Distance 局部变量或全局函数,并不会搜索全局函数引
" 用变量