If I source:let Mydict = { 'data': [0, 1, 2, 3] }fu! Mydict.mylen()    return len(self.data)endfuThen, I can execute echo Mydict.mylen() which returns 4 because it's the length of the list [0,1,2,3]. I didn't have to give the dict attribute to the function Mydict.mylen().If I source:fu! MyFunc() dict    return len(self.data)endfulet mydict = { 'data': [0, 1, 2, 3], 'mylen': function('MyFunc') }Then, I can execute echo mydict.mylen() which, again, returns 4, for the same reason as before. However, this time, I had to give the dict attribute to the function MyFunc(). Without dict, it would have raised the errors:E121: Undefined variable: selfE116: Invalid arguments for function len(self.data)E15: Invalid expression: len(self.data)If I source:fu! Order() dict    echo 'eat your ' . self.nameendfulet food       = { 'name': 'vegetables' }let BuildOrder = function('Order', food)Then, I can execute call BuildOrder(), which displays eat your vegetables. I had to give the dict attribute to the function Order(), for the same reason as before.If I source:fu! Describe(count, adj) dict    echo a:count.' '.a:adj.' '. self.nameendfulet animal      = { 'name': 'piggies' }let Description = function('Describe', [ 3 ], animal)Then, I can execute call Description('little'), which displays 3 little piggies. And again, I had to give the dict attribute to the Describe() function.dict is only needed in the last 3 of the 4 previous snippets. What does Vim do internally, which explains that dict is not needed in the first one, but is in all the others?And whatever it does, why doesn't it do it in the last 3 snippets? What would happen if it did it all the time, or never?
How is the `dict` attribute processed internally?
vimscript
This is described at :help Dictionary-function:                *Dictionary-function* *self* *E725* *E862*When a function is defined with the dict attribute it can be used in aspecial way with a dictionary.  Example: >    :function Mylen() dict    :   return len(self.data)    :endfunction    :let mydict = {'data': [0, 1, 2, 3], 'len': function(Mylen)}    :echo mydict.len()This is like a method in object oriented programming.  The entry in theDictionary is a |Funcref|.  The local variable self refers to the dictionarythe function was invoked from.It is also possible to add a function without the dict attribute as aFuncref to a Dictionary, but the self variable is not available then.                *numbered-function* *anonymous-function*To avoid the extra name for the function it can be defined and directlyassigned to a Dictionary in this way: >    :let mydict = {'data': [0, 1, 2, 3]}    :function mydict.len()    :   return len(self.data)    :endfunction    :echo mydict.len()The function will then get a number and the value of dict.len is a |Funcref|that references this function.  The function can only be used through a|Funcref|.  It will automatically be deleted when there is no |Funcref|remaining that refers to it.Both approaches define a function which will have access to their containing dict via the name self.The function mydict.len approach is just syntactic sugar to define the functions directly in the dictionary.  You can still assign that function to other dictionaries::let otherdict = { 'data': [0, 1], 'len': function(mydict.len) }:echo otherdict.len()2