Why somebody may think that there should be another item? Persons that
do not understand that {callback} should be attached to `'callback'`
key will as well not understand that {repeat} should be attached to
`'repeat'` key.
Also I did not see any problems with developers failing to understand
that ch_sendexpr() or job_start() should have handler attached to
`'callback'` key. This argument is nonsense to hear, I am not the one
that suggested to have {options} with `'callback'`, except that there
it is optional.
Several functions are absolutely fine, one may simply pass a “class
instance” as a callback.
// As a side note: why did you choose callback names so that they
cannot be called using dot-subscript notation (i.e.
`options.out_cb()`)? It is not uncommon when callback function is
reused for purposes other then being a callback, though I guess nobody
currently cares because one cannot use dictionary functions for
callbacks there, so writing `function options.out_cb(...)` is not
possible.
>
> Another objection to using the dictionary both for options and for
> passing to the callback is that it's not clear what happens if some of
> the option values is changed. Does that mean the changed value will be
> used?
This should be documented. In case of a repeating execution in some
cases it may actually be convenient to adjust interval by assigning
new value to `'interval'` key. And restarting is in any case easier if
everything is kept in one container:
```
let timer = {'interval': 1, 'Cookie': []}
function timer.callback() dict
call add(self.Cookie, 'test')
endfunction
function timer.enable() dict
call timer_add(self) " Should do nothing if timer was enabled
because dictionary is an identifier
endfunction
function timer.disable() dict
call timer_del(self)
endfunction
```
vs
```
function Callback(cookie)
call add(a:cookie, 'test')
endfunction
let g:timer = v:null
let g:cookie = []
function EnableTimer()
if g:timer is v:null " Needed because new timer_add will simply
make function run twice, callback is not an identifier
let g:timer = timer_add(1, function('Callback', [g:cookie]))
endif
endfunction
function DisableTimer()
call timer_del(g:timer)
let g:timer = v:null
endfunction
```
Using dictionary functions does not make much difference in the second case.
>
> I think it's better to separate options from any dictionary related to
> the callback. And there are many other places callbacks are used where
> binding it with arguments or a dictionary is useful.
Partial application is orthogonal to timer_* API. It is useful even
without any callbacks involved.
I would suggest function(name[, args[, self]]) instead where `args` is
a list. Otherwise you need to change `dict.Callback` expression to
produce “bound function”. It is not uncommon thing in OO languages,
but I do not remember this anywhere else.
E.g. in Python
s = 'test'
rep = s.replace
print(rep('e', ''))
will show `tst` because `s.replace` is a bound method (`print(rep)`
produces `<built-in method replace of str object at 0x7f0ad2ebac70>`
in Python 3 where 0x7f0ad2ebac70 is address of object to which `rep`
is bound).
Do not forget that bound functions need to hold references of the
object they are bound to.