blob: cabe55b31682155da3004058efd30d297d9cb372 [file] [log] [blame]
Bram Moolenaarf1dcd142022-12-31 15:30:45 +00001*vim9class.txt* For Vim version 9.0. Last change: 2022 Dec 20
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00002
3
4 VIM REFERENCE MANUAL by Bram Moolenaar
5
6
7NOTE - This is under development, anything can still change! - NOTE
8
9
10Vim9 classes, objects, interfaces, types and enums.
11
121. Overview |Vim9-class-overview|
132. A simple class |Vim9-simple-class|
143. Using an abstract class |Vim9-abstract-class|
154. Using an interface |Vim9-using-interface|
165. More class details |Vim9-class|
176. Type definition |Vim9-type|
187. Enum |Vim9-enum|
19
209. Rationale
2110. To be done later
22
23==============================================================================
24
251. Overview *Vim9-class-overview*
26
27The fancy term is "object-oriented programming". You can find lots of study
28material about this subject. Here we document what |Vim9| script provides,
29assuming you know the basics already. Added are helpful hints about how
30to use this functionality effectively.
31
32The basic item is an object:
33- An object stores state. It contains one or more variables that can each
34 have a value.
35- An object usually provides functions that manipulate its state. These
36 functions are invoked "on the object", which is what sets it apart from the
37 traditional separation of data and code that manipulates the data.
38- An object has a well defined interface, with typed member variables and
39 member functions.
40- Objects are created by a class and all objects have the same interface.
41 This never changes, it is not dynamic.
42
43An object can only be created by a class. A class provides:
44- A new() method, the constructor, which returns an object for the class.
45 This method is invoked on the class name: MyClass.new().
46- State shared by all objects of the class: class variables and constants.
47- A hierarchy of classes, with super-classes and sub-classes, inheritance.
48
49An interface is used to specify properties of an object:
50- An object can declare several interfaces that it implements.
51- Different objects implementing the same interface can be used the same way.
52
53The class hierarchy allows for single inheritance. Otherwise interfaces are
54to be used where needed.
55
56
57Class modeling ~
58
59You can model classes any way you like. Keep in mind what you are building,
60don't try to model the real world. This can be confusing, especially because
61teachers use real-world objects to explain class relations and you might think
62your model should therefore reflect the real world. It doesn't! The model
63should match your purpose.
64
65You will soon find that composition is often better than inheritance. Don't
66waste time trying to find the optimal class model. Or waste time discussing
67whether a square is a rectangle or that a rectangle is a square. It doesn't
68matter.
69
70
71==============================================================================
72
732. A simple class *Vim9-simple-class*
74
75Let's start with a simple example: a class that stores a text position: >
76
77 class TextPosition
78 this.lnum: number
79 this.col: number
80
81 def new(lnum: number, col: number)
82 this.lnum = lnum
83 this.col = col
84 enddef
85
86 def SetLnum(lnum: number)
87 this.lnum = lnum
88 enddef
89
90 def SetCol(col: number)
91 this.col = col
92 enddef
93
94 def SetPosition(lnum: number, col: number)
95 this.lnum = lnum
96 this.col = col
97 enddef
98 endclass
Bram Moolenaar7db29e42022-12-11 15:53:04 +000099< *object* *Object*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000100You can create an object from this class with the new() method: >
101
102 var pos = TextPosition.new(1, 1)
103
104The object members "lnum" and "col" can be accessed directly: >
105
106 echo $'The text position is ({pos.lnum}, {pos.col})'
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000107< *E1317* *E1327*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000108If you have been using other object-oriented languages you will notice that
109in Vim the object members are consistently referred to with the "this."
110prefix. This is different from languages like Java and TypeScript. This
111naming convention makes the object members easy to spot. Also, when a
112variable does not have the "this." prefix you know it is not an object member.
113
114
115Member write access ~
116
117Now try to change an object member directly: >
118
119 pos.lnum = 9
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000120< *E1335*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000121This will give you an error! That is because by default object members can be
122read but not set. That's why the class provides a method for it: >
123
124 pos.SetLnum(9)
125
126Allowing to read but not set an object member is the most common and safest
127way. Most often there is no problem using a value, while setting a value may
128have side effects that need to be taken care of. In this case, the SetLnum()
129method could check if the line number is valid and either give an error or use
130the closest valid value.
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000131 *:public* *E1331*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000132If you don't care about side effects and want to allow the object member to be
133changed at any time, you can make it public: >
134
135 public this.lnum: number
136 public this.col number
137
138Now you don't need the SetLnum(), SetCol() and SetPosition() methods, setting
139"pos.lnum" directly above will no longer give an error.
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000140 *E1334*
141If you try to set an object member that doesn't exist you get an error: >
142 pos.other = 9
143< E1334: Object member not found: other ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000144
145
146Private members ~
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000147 *E1332* *E1333*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000148On the other hand, if you do not want the object members to be read directly,
149you can make them private. This is done by prefixing an underscore to the
150name: >
151
152 this._lnum: number
153 this._col number
154
155Now you need to provide methods to get the value of the private members.
156These are commonly call getters. We recommend using a name that starts with
157"Get": >
158
159 def GetLnum(): number
160 return this._lnum
161 enddef
162
163 def GetCol() number
164 return this._col
165 enddef
166
167This example isn't very useful, the members might as well have been public.
168It does become useful if you check the value. For example, restrict the line
169number to the total number of lines: >
170
171 def GetLnum(): number
172 if this._lnum > this._lineCount
173 return this._lineCount
174 endif
175 return this._lnum
176 enddef
177
178
179Simplifying the new() method ~
180
181Many constructors take values for the object members. Thus you very often see
182this pattern: >
183
184 this.lnum: number
185 this.col: number
186
187 def new(lnum: number, col: number)
188 this.lnum = lnum
189 this.col = col
190 enddef
191
192Not only is this text you need to write, it also has the type of each member
193twice. Since this is so common a shorter way to write new() is provided: >
194
195 def new(this.lnum, this.col)
196 enddef
197
198The semantics are easy to understand: Providing the object member name,
199including "this.", as the argument to new() means the value provided in the
200new() call is assigned to that object member. This mechanism is coming from
201the Dart language.
202
203The sequence of constructing a new object is:
2041. Memory is allocated and cleared. All values are zero/false/empty.
2052. For each declared member that has an initializer, the expression is
206 evaluated and assigned to the member. This happens in the sequence the
207 members are declared in the class.
2083. Arguments in the new() method in the "this.name" form are assigned.
2094. The body of the new() method is executed.
210
211TODO: for a sub-class the constructor of the parent class will be invoked
212somewhere.
213
214
215==============================================================================
216
2173. Using an abstract class *Vim9-abstract-class*
218
219An abstract class forms the base for at least one sub-class. In the class
220model one often finds that a few classes have the same properties that can be
221shared, but a class with those properties does not have enough state to create
222an object from. A sub-class must extend the abstract class and add the
223missing state and/or methods before it can be used to create objects for.
224
225An abstract class does not have a new() method.
226
227For example, a Shape class could store a color and thickness. You cannot
228create a Shape object, it is missing the information about what kind of shape
229it is. The Shape class functions as the base for a Square and a Triangle
230class, for which objects can be created. Example: >
231
232 abstract class Shape
233 this.color = Color.Black
234 this.thickness = 10
235 endclass
236
237 class Square extends Shape
238 this.size: number
239
240 def new(this.size)
241 enddef
242 endclass
243
244 class Triangle extends Shape
245 this.base: number
246 this.height: number
247
248 def new(this.base, this.height)
249 enddef
250 endclass
251<
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000252 *class-member* *:static* *E1337* *E1338*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000253Class members are declared with "static". They are used by the name without a
254prefix: >
255
256 class OtherThing
257 this.size: number
258 static totalSize: number
259
260 def new(this.size)
261 totalSize += this.size
262 enddef
263 endclass
264<
265 *class-method*
266Class methods are also declared with "static". They have no access to object
267members, they cannot use the "this" keyword. >
268
269 class OtherThing
270 this.size: number
271 static totalSize: number
272
273 " Clear the total size and return the value it had before.
274 static def ClearTotalSize(): number
275 var prev = totalSize
276 totalSize = 0
277 return prev
278 enddef
279 endclass
280
281
282==============================================================================
283
2844. Using an interface *Vim9-using-interface*
285
286The example above with Shape, Square and Triangle can be made more useful if
287we add a method to compute the surface of the object. For that we create the
288interface called HasSurface, which specifies one method Surface() that returns
289a number. This example extends the one above: >
290
291 abstract class Shape
292 this.color = Color.Black
293 this.thickness = 10
294 endclass
295
296 interface HasSurface
297 def Surface(): number
298 endinterface
299
300 class Square extends Shape implements HasSurface
301 this.size: number
302
303 def new(this.size)
304 enddef
305
306 def Surface(): number
307 return this.size * this.size
308 enddef
309 endclass
310
311 class Triangle extends Shape implements HasSurface
312 this.base: number
313 this.height: number
314
315 def new(this.base, this.height)
316 enddef
317
318 def Surface(): number
319 return this.base * this.height / 2
320 enddef
321 endclass
322
323The interface name can be used as a type: >
324
325 var shapes: list<HasSurface> = [
326 Square.new(12),
327 Triangle.new(8, 15),
328 ]
329 for shape in shapes
330 echo $'the surface is {shape.Surface()}'
331 endfor
332
333
334==============================================================================
335
Bram Moolenaar7db29e42022-12-11 15:53:04 +00003365. More class details *Vim9-class* *Class* *class*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000337
338Defining a class ~
339 *:class* *:endclass* *:abstract*
340A class is defined between `:class` and `:endclass`. The whole class is
341defined in one script file. It is not possible to add to a class later.
342
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000343A class can only be defined in a |Vim9| script file. *E1316*
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000344A class cannot be defined inside a function.
345
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000346It is possible to define more than one class in a script file. Although it
347usually is better to export only one main class. It can be useful to define
348types, enums and helper classes though.
349
350The `:abstract` keyword may be prefixed and `:export` may be used. That gives
351these variants: >
352
353 class ClassName
354 endclass
355
356 export class ClassName
357 endclass
358
359 abstract class ClassName
360 endclass
361
362 export abstract class ClassName
363 endclass
364<
365 *E1314*
366The class name should be CamelCased. It must start with an uppercase letter.
367That avoids clashing with builtin types.
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000368 *E1315*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000369After the class name these optional items can be used. Each can appear only
370once. They can appear in any order, although this order is recommended: >
371 extends ClassName
372 implements InterfaceName, OtherInterface
373 specifies SomeInterface
374< *extends*
375A class can extend one other class.
376 *implements*
377A class can implement one or more interfaces.
378 *specifies*
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000379A class can declare its interface, the object members and methods, with a
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000380named interface. This avoids the need for separately specifying the
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000381interface, which is often done in many languages, especially Java.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000382
383
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000384Items in a class ~
385 *E1318* *E1325* *E1326*
386Inside a class, in betweeen `:class` and `:endclass`, these items can appear:
387- An object member declaration: >
388 this._memberName: memberType
389 this.memberName: memberType
390 public this.memberName: memberType
391- A constructor method: >
392 def new(arguments)
393 def newName(arguments)
394- An object method: >
395 def SomeMethod(arguments)
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000396< *E1329*
397For the object member the type must be specified. The best way is to do this
398explicitly with ": {type}". For simple types you can also use an initializer,
399such as "= 123", and Vim will see that the type is a number. Avoid doing this
400for more complex types and when the type will be incomplete. For example: >
401 this.nameList = []
402This specifies a list, but the item type is unknown. Better use: >
403 this.nameList: list<string>
404The initialization isn't needed, the list is empty by default.
405 *E1330*
406Some types cannot be used, such as "void", "null" and "v:none".
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000407
408
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000409Defining an interface ~
410 *:interface* *:endinterface*
411An interface is defined between `:interface` and `:endinterface`. It may be
412prefixed with `:export`: >
413
414 interface InterfaceName
415 endinterface
416
417 export interface InterfaceName
418 endinterface
419
420An interface can declare object members, just like in a class but without any
421initializer.
422
423An interface can declare methods with `:def`, including the arguments and
424return type, but without the body and without `:enddef`. Example: >
425
426 interface HasSurface
427 this.size: number
428 def Surface(): number
429 endinterface
430
431The "Has" prefix can be used to make it easier to guess this is an interface
432name, with a hint about what it provides.
433
434
435Default constructor ~
436
437In case you define a class without a new() method, one will be automatically
438defined. This default constructor will have arguments for all the object
439members, in the order they were specified. Thus if your class looks like: >
440
441 class AutoNew
442 this.name: string
443 this.age: number
444 this.gender: Gender
445 endclass
446
447Then The default constructor will be: >
448
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000449 def new(this.name = v:none, this.age = v:none, this.gender = v:none)
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000450 enddef
451
452All object members will be used, also private access ones.
453
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000454The "= v:none" default values make the arguments optional. Thus you can also
455call `new()` without any arguments. No assignment will happen and the default
456value for the object members will be used. This is a more useful example,
457with default values: >
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000458
459 class TextPosition
460 this.lnum: number = 1
461 this.col: number = 1
462 endclass
463
464If you want the constructor to have mandatory arguments, you need to write it
465yourself. For example, if for the AutoNew class above you insist on getting
466the name, you can define the constructor like this: >
467
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000468 def new(this.name, this.age = v:none, this.gender = v:none)
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000469 enddef
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000470< *E1328*
471Note that you cannot use another default value than "v:none" here. If you
472want to initialize the object members, do it where they are declared. This
473way you only need to look in one place for the default values.
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000474
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000475
476Multiple constructors ~
477
478Normally a class has just one new() constructor. In case you find that the
479constructor is often called with the same arguments you may want to simplify
480your code by putting those arguments into a second constructor method. For
481example, if you tend to use the color black a lot: >
482
483 def new(this.garment, this.color, this.size)
484 enddef
485 ...
486 var pants = new(Garment.pants, Color.black, "XL")
487 var shirt = new(Garment.shirt, Color.black, "XL")
488 var shoes = new(Garment.shoes, Color.black, "45")
489
490Instead of repeating the color every time you can add a constructor that
491includes it: >
492
493 def newBlack(this.garment, this.size)
494 this.color = Color.black
495 enddef
496 ...
497 var pants = newBlack(Garment.pants, "XL")
498 var shirt = newBlack(Garment.shirt, "XL")
499 var shoes = newBlack(Garment.shoes, "9.5")
500
501Note that the method name must start with "new". If there is no method called
502"new()" then the default constructor is added, even though there are other
503constructor methods.
504
505
506==============================================================================
507
5086. Type definition *Vim9-type* *:type*
509
510A type definition is giving a name to a type specification. For Example: >
511
512 :type ListOfStrings list<string>
513
514TODO: more explanation
515
516
517==============================================================================
518
5197. Enum *Vim9-enum* *:enum* *:endenum*
520
521An enum is a type that can have one of a list of values. Example: >
522
523 :enum Color
524 White
525 Red
526 Green
527 Blue
528 Black
529 :endenum
530
531TODO: more explanation
532
533
534==============================================================================
535
5369. Rationale
537
538Most of the choices for |Vim9| classes come from popular and recently
539developed languages, such as Java, TypeScript and Dart. The syntax has been
540made to fit with the way Vim script works, such as using `endclass` instead of
541using curly braces around the whole class.
542
543Some common constructs of object-oriented languages were chosen very long ago
544when this kind of programming was still new, and later found to be
545sub-optimal. By this time those constructs were widely used and changing them
546was not an option. In Vim we do have the freedom to make different choices,
547since classes are completely new. We can make the syntax simpler and more
548consistent than what "old" languages use. Without diverting too much, it
549should still mostly look like what you know from existing languages.
550
551Some recently developed languages add all kinds of fancy features that we
552don't need for Vim. But some have nice ideas that we do want to use.
553Thus we end up with a base of what is common in popular languages, dropping
554what looks like a bad idea, and adding some nice features that are easy to
555understand.
556
557The main rules we use to make decisions:
558- Keep it simple.
559- No surprises, mostly do what other languages are doing.
560- Avoid mistakes from the past.
561- Avoid the need for the script writer to consult the help to understand how
562 things work, most things should be obvious.
563- Keep it consistent.
564- Aim at an average size plugin, not at a huge project.
565
566
567Using new() for the constructor ~
568
569Many languages use the class name for the constructor method. A disadvantage
570is that quite often this is a long name. And when changing the class name all
571constructor methods need to be renamed. Not a big deal, but still a
572disadvantage.
573
574Other languages, such as TypeScript, use a specific name, such as
575"constructor()". That seems better. However, using "new" or "new()" to
576create a new object has no obvious relation with "constructor()".
577
578For |Vim9| script using the same method name for all constructors seemed like
579the right choice, and by calling it new() the relation between the caller and
580the method being called is obvious.
581
582
583No overloading of the constructor ~
584
585In Vim script, both legacy and |Vim9| script, there is no overloading of
586functions. That means it is not possible to use the same function name with
587different types of arguments. Therefore there also is only one new()
588constructor.
589
590With |Vim9| script it would be possible to support overloading, since
591arguments are typed. However, this gets complicated very quickly. Looking at
592a new() call one has to inspect the types of the arguments to know which of
593several new() methods is actually being called. And that can require
594inspecting quite a bit of code. For example, if one of the arguments is the
595return value of a method, you need to find that method to see what type it is
596returning.
597
598Instead, every constructor has to have a different name, starting with "new".
599That way multiple constructors with different arguments are possible, while it
600is very easy to see which constructor is being used. And the type of
601arguments can be properly checked.
602
603
604No overloading of methods ~
605
606Same reasoning as for the constructor: It is often not obvious what type
607arguments have, which would make it difficult to figure out what method is
608actually being called. Better just give the methods a different name, then
609type checking will make sure it works as you intended. This rules out
610polymorphism, which we don't really need anyway.
611
612
613Using "this.member" everywhere ~
614
615The object members in various programming languages can often be accessed in
616different ways, depending on the location. Sometimes "this." has to be
617prepended to avoid ambiguity. They are usually declared without "this.".
618That is quite inconsistent and sometimes confusing.
619
620A very common issue is that in the constructor the arguments use the same name
621as the object member. Then for these members "this." needs to be prefixed in
622the body, while for other members this is not needed and often omitted. This
623leads to a mix of members with and without "this.", which is inconsistent.
624
625For |Vim9| classes the "this." prefix is always used. Also for declaring the
626members. Simple and consistent. When looking at the code inside a class it's
627also directly clear which variable references are object members and which
628aren't.
629
630
631Single inheritance and interfaces ~
632
633Some languages support multiple inheritance. Although that can be useful in
634some cases, it makes the rules of how a class works quite complicated.
635Instead, using interfaces to declare what is supported is much simpler. The
636very popular Java language does it this way, and it should be good enough for
637Vim. The "keep it simple" rule applies here.
638
639Explicitly declaring that a class supports an interface makes it easy to see
640what a class is intended for. It also makes it possible to do proper type
641checking. When an interface is changed any class that declares to implement
642it will be checked if that change was also changed. The mechanism to assume a
643class implements an interface just because the methods happen to match is
644brittle and leads to obscure problems, let's not do that.
645
646
647Using class members ~
648
649Using "static member" to declare a class member is very common, nothing new
650here. In |Vim9| script these can be accessed directly by their name. Very
651much like how a script-local variable can be used in a function. Since object
652members are always accessed with "this." prepended, it's also quickly clear
653what kind of member it is.
654
655TypeScript prepends the class name before the class member, also inside the
656class. This has two problems: The class name can be rather long, taking up
657quite a bit of space, and when the class is renamed all these places need to
658be changed too.
659
660
661Using "ClassName.new()" to construct an object ~
662
663Many languages use the "new" operator to create an object, which is actually
664kind of strange, since the constructor is defined as a method with arguments,
665not a command. TypeScript also has the "new" keyword, but the method is
666called "constructor()", it is hard to see the relation between the two.
667
668In |Vim9| script the constructor method is called new(), and it is invoked as
669new(), simple and straightforward. Other languages use "new ClassName()",
670while there is no ClassName() method, it's a method by another name in the
671class called ClassName. Quite confusing.
672
673
674Default read access to object members ~
675
676Some users will remark that the access rules for object members are
677asymmetric. Well, that is intentional. Changing a value is a very different
678action than reading a value. The read operation has no side effects, it can
679be done any number of times without affecting the object. Changing the value
680can have many side effects, and even have a ripple effect, affecting other
681objects.
682
683When adding object members one usually doesn't think much about this, just get
684the type right. And normally the values are set in the new() method.
685Therefore defaulting to read access only "just works" in most cases. And when
686directly writing you get an error, which makes you wonder if you actually want
687to allow that. This helps writing code with fewer mistakes.
688
689
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000690Making object members private with an underscore ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000691
692When an object member is private, it can only be read and changed inside the
693class (and in sub-classes), then it cannot be used outside of the class.
694Prepending an underscore is a simple way to make that visible. Various
695programming languages have this as a recommendation.
696
697In case you change your mind and want to make the object member accessible
698outside of the class, you will have to remove the underscore everywhere.
699Since the name only appears in the class (and sub-classes) they will be easy
700to find and change.
701
702The other way around is much harder: you can easily prepend an underscore to
703the object member inside the class to make it private, but any usage elsewhere
704you will have to track down and change. You may have to make it a "set"
705method call. This reflects the real world problem that taking away access
706requires work to be done for all places where that access exists.
707
708An alternative would have been using the "private" keyword, just like "public"
709changes the access in the other direction. Well, that's just to reduce the
710number of keywords.
711
712
713No protected object members ~
714
715Some languages provide several ways to control access to object members. The
716most known is "protected", and the meaning varies from language to language.
717Others are "shared", "private" and even "friend".
718
719These rules make life more difficult. That can be justified in projects where
720many people work on the same, complex code where it is easy to make mistakes.
721Especially when refactoring or other changes to the class model.
722
723The Vim scripts are expected to be used in a plugin, with just one person or a
724small team working on it. Complex rules then only make it more complicated,
725the extra safety provide by the rules isn't really needed. Let's just keep it
726simple and not specify access details.
727
728
729==============================================================================
730
73110. To be done later
732
733Can a newSomething() constructor invoke another constructor? If yes, what are
734the restrictions?
735
736Thoughts:
737- Generics for a class: `class <Tkey, Tentry>`
738- Generics for a function: `def <Tkey> GetLast(key: Tkey)`
739- Mixins: not sure if that is useful, leave out for simplicity.
740
741Some things that look like good additions:
742- For testing: Mock mechanism
743
744An important class to be provided is "Promise". Since Vim is single
745threaded, connecting asynchronous operations is a natural way of allowing
746plugins to do their work without blocking the user. It's a uniform way to
747invoke callbacks and handle timeouts and errors.
748
749
750 vim:tw=78:ts=8:noet:ft=help:norl: