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
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 局部变量或全局函数,并不会搜索全局函数引
|
||
|
" 用变量
|