Sorunuzu cevaplamak için: call()
kılavuzdaki prototip call({func}, {arglist} [, {dict}])
; {arglist}
argüman bağımsız değişkenler listesi tam anlamıyla bir Liste nesnesi değil, olması gerekiyor. Yani, şöyle yazmalısınız:
let @x = call(a:functionToExecute, [GetSelectedText()])
Bu a:functionToExecute
, bir Funcref (bkz. :help Funcref
) Veya bir işlevin adıdır (örneğin, bir dize 'Type1ProcessString'
).
Şimdi, bu Vim'e bir çeşit LISP benzeri kalite veren güçlü bir özellik, ancak muhtemelen nadiren yukarıdaki gibi kullanabilirsiniz. Eğer a:functionToExecute
bir dize, bir fonksiyonun adıdır, o zaman bunu yapabilirsiniz:
function! Wrapper(functionToExecute)
" ...
let s:processing = function(a:functionToExecute)
let @x = s:processing(GetSelectedText())
" ...
endfunction
ve sarmalayıcıyı işlevin adıyla çağırırsınız:
call Wrapper('Type1ProcessString')
Öte yandan a:functionToExecute
bir Funcref ise, doğrudan arayabilirsiniz:
function! Wrapper(functionToExecute)
" ...
let @x = a:functionToExecute(GetSelectedText())
" ...
endfunction
ancak sarmalayıcıyı şöyle çağırmanız gerekir:
call Wrapper(function('Type1ProcessString'))
İle fonksiyonların varlığını kontrol edebilirsiniz exists('*name')
. Bu, aşağıdaki küçük numarayı mümkün kılar:
let s:width = function(exists('*strwidth') ? 'strwidth' : 'strlen')
yani strwidth()
Vim'in sahip olacağı kadar yeniyse yerleşik olanı kullanan bir işlevdir ve strlen()
aksi halde geri döner (böyle bir geri dönüşün mantıklı olduğunu savunmuyorum; sadece yapılabileceğini söylüyorum). :)
Sözlük işlevleriyle (bkz. :help Dictionary-function
) Sınıflara benzeyen bir şey tanımlayabilirsiniz:
let g:MyClass = {}
function! g:MyClass.New(...)
let newObj = copy(self)
if a:0 && type(a:1) == type({})
let newObj._attributes = deepcopy(a:1)
endif
if exists('*MyClassProcess')
let newObj._process = function('MyClassProcess')
else
let newObj._process = function('s:_process_default')
endif
return newObj
endfunction
function! g:MyClass.getFoo() dict
return get(get(self, '_attributes', {}), 'foo')
endfunction
function! g:MyClass.setFoo(val) dict
if !has_key(self, '_attributes')
let self._attributes = {}
endif
let self._attributes['foo'] = a:val
endfunction
function! g:MyClass.process() dict
call self._process()
endfunction
function! s:_process_default()
echomsg 'nothing to see here, define MyClassProcess() to make me interesting'
endfunction
Sonra bunun gibi nesneleri başlatırsınız:
let little_object = g:MyClass.New({'foo': 'bar'})
Ve yöntemlerini çağırın:
call little_object.setFoo('baz')
echomsg little_object.getFoo()
call little_object.process()
Ayrıca sınıf özniteliklerine ve yöntemlerine de sahip olabilirsiniz:
let g:MyClass.__meaning_of_life = 42
function g:MyClass.GetMeaningOfLife()
return get(g:MyClass, '__meaning_of_life')
endfunction
( dict
burada gerek olmadığına dikkat edin ).
Düzenleme: Alt sınıflama şöyle bir şeydir:
let g:MySubclass = copy(g:MyClass)
call extend(g:MySubclass, subclass_attributes)
Buradaki ince nokta copy()
bunun yerine kullanımıdır deepcopy()
. Bunun nedeni, üst sınıfın özniteliklerine başvuru ile erişebilmektir. Bu elde edilebilir, ancak son derece kırılgandır ve doğru yapmak önemsiz olmaktan uzaktır. Bir diğer potansiyel sorun alt sınıf bir arada tutmaya çalışıyor ki bu tür is-a
ile has-a
. Bu nedenle sınıf özellikleri genellikle acıya değmez.
Tamam, bu düşünce için yiyecek vermek için yeterli olmalı.
İlk kod snippet'inize geri döndüğünüzde, geliştirilebilecek iki ayrıntı vardır:
- İhtiyacınız olmayan
normal gvd
, eski seçimi kaldırmak için normal "xp
önce onu öldürmek olmasa bile değiştirecektir
call setreg('x', [lines], type)
yerine kullanın let @x = [lines]
. Bu, kayıt türünü açıkça ayarlar x
. Aksi takdirde, x
zaten doğru tipe (yani, karakterize, çizgisel veya blok halinde) güveniyorsunuz .
dict
anahtar kelimeye ihtiyacınız yoktur . Bu, "sınıf yöntemleri" için geçerlidir. Bkz:h numbered-function
.