This is quite a large update. Section 4 is just under 1,000 lines now, which is around twice the extent. Many of the additional lines are to include educational, sourceable examples.
Locations of changes are indicated by reference to headings and *tags* in the updated file rather than line numbers. That mostly works well, though some of the more heavily edited passages are trickier to compare easily 1:1 to the current help.
*vim9-types*
The error tags appearing with the heading of section 4 are relocated:
*E1008*
, *E1009*
, *E1010*
, and *E1012*
are moved after the types table and the “no simple value can have the "void" type” example. They include one-line sourceable examples, and mostly relate to ill-formed declarations.*E1013*
, *E1029*
, and *E1030*
are moved to the passage containing the examples demonstrating legacy Vim script versus Vim9 script differences (i.e., under Stricter type checking
).“The following builtin types”, list is missing five types:
They are included now, and the order of the list is changed to the order of the values of v:t_TYPE
. It’s helpful to have the types, their v:t_TYPE
and their type()
shown, so a tabular format is used. Applicable hot-links to v:t_TYPE
, type()
, and the v:t_
types are added too.
*E1031* *E1186*
E1031
and E1186
. Rather than their tags being inline, they are moved to the more usual location, before the paragraph.*E1008* *E1009* *E1010* *E1012*
[The first paragraph and its examples are explained above]
“There is no array type...”, does not include tuple, which is interesting because tuple-type
is introduced immediately after it. The second sentence addresses that, though now it focuses on the concept (“use a list or tuple”) leaving the sourceable code to demonstrate the syntax. The tangential memory allocation point is omitted because, although it is not wrong, it is trivial in the wider context (learning/understanding Vim9 script) so, it seems unnecessary. Also, “literal” is used rather than “constant” because, aside from being less confusing - a tuple is a constant - it aligns with:
vim9-literal-dict
)*literal-string*
, *literal-Dict*
, etc.), and*tuple-type*
*vim9-func-declaration*, et al.
*vim9-partial-declaration*
, is added.*vim9-{type}-type*
, *vim9-func-type*
is added. That way, :h -type
CTRL-D should reveal all the Vim9 script type tags.|Partial|
(in eval.txt
). So, providing a complete, interactive example makes sense. It is only eight lines and should help not only those wanting to understand partials in Vim9 script, but also partials generally. A second example could be added (or used instead), though, perhaps that would be too much? The area of a circle example has the advantage of being simple and interactive. Using a dictionary, which would cover the second point in, “stores extra arguments and/or a dictionary”, could be added to eval.txt
? Something like this: vim9script
var animals = ['penguin', 'gnu', 'gopher', 'cat', 'python', 'camel']
def Compare(key: string, a: string, b: string): number
var dic = { alpha: () => a < b, length: () => len(a) < len(b) }
return dic[key]() ? -1 : 1
enddef
const ALPHA: func(string, string): number = function(Compare, ['alpha'])
const LENGTH: func(string, string): number = function(Compare, ['length'])
echo $"Unsorted animals: {animals}"
echo $"Sorted (alpha): {animals->sort(ALPHA)}"
echo $"Sorted (length): {animals->sort(LENGTH)}"
*vim9-typealias-type*
The tag *vim9-typealias-type*
is added (for the same reasons as explained, above). This is a distinct topic, so should have its own tag. It is covered in vim9class.txt
too, though it should be here too as an overview in the context of explaining Vim9 script types generally.
“Custom types ...” had only a one-line example. The updated paragraph covers the requirement to start with a capital letter and provides a simple example to show how custom types can be used. There is some overlap with vim9class.txt
, which also provides an example, though it feels helpful to provide more than incidental content in vim9.txt
on this topic, and it is not long. It is also warranted because of the following point.
*E1105*
*E1105*
tag is relocated from “Stricter Type Checking” (which is around 280 lines later in vim9.txt now) because that error relates specifically to the typealias topic and so it is better here than in the comparative (to legacy Vim script) content. It is also relocated because its current location does not relate to what it claims to address (i.e., “- Using a number where a string is expected. ... *E1105*”). A simple example demonstrates E1105
, which should be helpful for anyone going to the tag.*vim9-class-type*, *vim9-object-type* and *vim9-interface-type*
The three tags are added for completeness and consistency, following the established approach outlined, above.
“And classes and interfaces can be used as types”: The current help only has a brief statement with incomplete, non-sourceable examples. A terse example cannot adequately demonstrate how class, object, and interface types work together, so a comprehensive interactive example is warranted. The complete example provided should be useful for readers wanting to understand how to use the three types. Like typealias
, above, it includes output for type()
and typename()
, which should also help readers appreciate v:t_class
(for class and interface) and v:t_object
. It strikes the right balance:
foobar
).The text, “{not implemented yet}” is removed because it is not applicable now.
Note: Although there are some useful examples of using classes in vim9class.txt
there are no complete examples of using interfaces, so, adding this example is helpful. (vim9class.txt
probably should be updated too, but that is beyond the scope of this update.)
*vim9-enum-type* and *vim9-enumvalue-type*
The two tags are added for completeness and consistency.
There was no information in vim9.txt
on enum
or enumvalue
types. A paragraph explaining them is added. (As noted at the outset, neither enum
nor enumvalue
is in the list of types, which is also addressed.)
A complete, interactive example demonstrating enum
as a type is included. Similar to class
, object
, and interface
, it’s not easy to provide a succinct, sourceable script, though the example covers a lot of ground. The type()
and typename()
information is presented too, which is particularly interesting because the type()
values differ (as expected) for "Quad" (the enum itself) and "myQuad" (an enumvalue), yet their typename()
s are both enum<Quad>
.
*variable types*
list<any>
is used versus overtly checking the variable’s type, so, the paragraph is reworded.*type casting*
The tag *E1104*
is relocated to a few paragraphs later (where its applicable error is explained and demonstrated).
“To avoid this, use a type cast”, is adjusted too. Now it homes in on the key point, i.e., to get more specific type checking.
A sourceable example is added to demonstrate type casting. Both functions produce E1012
errors due to type mismatches, but the type checking occurs at different points. The example uses try/catch blocks to make it fully executable, revealing the different error messages.
“The semantics is that...”, is awkward, so it is changed to align with the revised points, above.
The line, "If a type is given where it is not expected you can get *E1272* .", is removed. It appears this is not an error that ever occurs? (There is no evidence of it in src/testdir
; perhaps it was intended, though never implemented? The only instance of it appearing in the source code is in src/errors.h
, "E1272: Using type not in a script context: %s"
, but there are no test files for it. So, it could be reinstated, though should only be reverted if it really is a reachable error, preferably with a demonstrable example.
Type casting on chained expressions is added because the point should be included, i.e., the type cast applies to the whole expression, not the first element within it.
*E1363*
*E1363*
occurs, so it, along with |E1360|
(another error close to the topic), are provided with sourceable examples. The *E1363*
tag is relocated to before the passage.The opening paragraph has been expanded to connect to the points in the preceding section.
The example has been made complete, sourceable, and four more types are included. The output shows each variable’s value, its type()
number (corresponding to v:t_*
constants), and its typename()
, which should help improve understanding.
“The type of a list and dictionary” has the tuple
type added, and the paragraph adjusted to reflect the “mix of types” list, which is enhanced by including typename()
as well as dictionary and tuple examples, which makes sense since the paragraph now introduces all three.
“The common type of function references” paragraph has been modified to improve readability and introduce the example, which is now sourceable.
The remainder of this sub-section has improved wording and examples. This includes addressing, “If the type is not declared then it is allowed to change”, which could be misinterpreted as meaning a var
with no type explicitly stated may be changed, whereas that is not right because it will either be inferred as a type or be 'any' - the point is meant to be that a list literal or dictionary literal’s type may change, which is what is demonstrated now.
*type-checking*
*E1206*
*E1210*
and *E1212*
, located alongside *E1206*
, are moved to separate examples because they are not examples of where “it works just as before”, whereas that is true for E1206
. So, only E1260
remains as the tag relevant to the paragraph, i.e., errors universally common-to-both languages. (I expect that's right because using something other than a dictionary where one is required is unlikely to be accommodated in any instance whereas it is clear that numbers, strings, etc., may be coerced in legacy Vim script, e.g., 8
to v:true
- as :if 8 | echo 'yes' | endif
does - and so forth.)*E1023* *E1024* *E1029* *E1030* *E1210* *E1212*
These tags have been brought together as a common group. That is, they are the instances:
Bringing them together is more helpful than the currently scattered arrangement. It would probably take a reader a while to think about the scenarios that may cause these errors; so, the examples provided should make it easier for readers to grasp the differences, including if following hot-links to the tags.
There are several other type-related errors in Vim9 script, which do not error in legacy Vim script. The ones included now are: E521
, E928
, E1037
, E1072
, E1135
, E1138
, and E1174
). The reason for them appearing after the ones noted in the point above are that these are different in that they have documentation and corresponding tags elsewhere. This collection covers a lot more than in the current help, though it feels warranted given these are important distinctions. Hot-links are provided to the seven applicable tags.
E1037
differences are unusual, illustrating inconsistent treatment in Vim9 script regarding v:none
versus v:null
/null
; this does not error when compared to a number or bool (or anything other than the “Specials”, v:none
and v:null
). Perhaps it is intentional behaviour, though it is an open issue, #17358 (labelled as a bug).#
comments are added for the E
messages in all instances of the vim9cmd
commands other than E521
and E1138
, which do not syntax highlight the comment correctly - they could be made vim9script
, but that would add several lines and look inconsistent with the other examples. (The same applies to E1030's example, though its comment has been retained as it is not so glaring in appearance since it is all the same highlight group.)The “One consequence...” paragraph is enhanced to explain that it applies whether declared or inferred. The example is also improved by making it sourceable, showing how in legacy Vim script there is no problem changing the type of a list whereas trying to use map()
on the same list in Vim9 script results in an E1012
error because the type is inferred as list<number>
.
This example in the current help is incorrect:
If the item type was not declared or determined to be "any" it can change
to a more specific type. E.g. when a list of mixed types gets changed to
a list of strings:
var mylist = [1, 2.0, '3']
# typename(mylist) == "list<any>"
map(mylist, (i, v) => 'item ' .. i)
# typename(mylist) == "list<string>", no error
...which is the same as this:
vim9script
var mylist = [1, 2.0, '3']
map(mylist, (i, _) => $"item {i}")
echo mylist->typename() # list<any>
Clearly, typename()
does NOT change from list<any>
. It can only become list<string>
if mapnew()
is used (logically, because then it is inferred that all the list items are strings). So, that is shown, now with an extended example and commenting.
Further examples and expanded explanations are provided in relation to the “subtle difference between using a list constant directly”, which does not feel as clear it could be. The complete examples, including the list literal and deepcopy()
are wrapped up in a slightly longer “reasoning” explanation.
*E1158*
The extend()
and extendnew()
examples are separated (now located before tag *E1158*
) from flatten()
and flattennew()
because the former are both allowed in Vim9 script – examples are provided showing that – whereas flatten()
is prohibited entirely (producing an E1158
error) even for literals.
The funcref
with specified arguments passage was quite condensed. It now progresses clearly, with complete examples. It concludes with what had not been covered, which is, in some scenarios, any
may allow for mixed types.
The funcref with no arguments specified explanation is made clearer and has a sourceable example. The FlexArgs
funcref shows using a string-returning
function with:
*E1211* to ... *E1534*
The current help provides only a “wall” of error tags with one generic sentence. Without examples, users encountering this may not easily determine what causes the errors nor how to fix them, especially if they :h E{nnnn}
wanting to find out more about a specific error. Sourceable one-line examples of 25 of the 28 errors are included, which is more helpful.
tuple
, which should be rare). If a function’s type requirements change, the corresponding error may need changing here too, though updating it here would require just a one-line change.vim9
is used here rather than full commands to maximise the length of the truncated error messages in comments, keeping to <80 characters text width. Error messages are vertically aligned to aid readers’ ability to scan the “list”.The three error tags, *E1227*
, *E1250*
, and *E1252*
, are separated and noted as “Reserved for future use”. There appears to be no current builtin functions that produce these errors? This approach maintains the existing tags as placeholders, which presumably were included so that if/when these errors are applicable in future, their help entries can be easily located?
The current help provides only three generic examples (one per category) without demonstrating actual behaviour. The revision provides comprehensive, sourceable examples for all 13 types, showing each type’s default value, its empty()
status, and whether it equals null
. This clarifies and demonstrates important distinctions:
empty()
but not null
null
among containers, andnull
.The paragraph, “Vim does not have a familiar null value”, has had small refinements.
The examples under, “For a specialized variable” and “For a container variable” (showing how to clear specialized and container variables respectively) are separated into distinct code blocks because they demonstrate different clearing mechanics. Both examples are now complete and sourceable. The job example is particularly helpful as it provides a working, cross-platform demonstration (using &shell
and &shellcmdflag
with the O/S shell’s 'date' command), which is something absent in the current help documentation.
“The initialization semantics of container and specialized variables” sentence is separated from the containers-related sentence because the content was, and remains, separately explained.
The containers example is preceded with an itemised explanation, then demonstrated with a working example, showing the equivalence of all three declarations but also the difference between the null_list
and either of the initialised or uninitialized empty list containers.
The job
passage is mostly unchanged, though the example is now sourceable with an echoed equivalency expression demonstrating their indistinguishable nature.
The paragraph, “When a list...”, is updated to include tuple
, and the point it makes is separated into two sentences to make it easier to understand. The updated, sourceable code block now echoes the typename()
for the empty and null tuple, showing that both empty and null tuples default to tuple<any>
.
The paragraph, “Declaring a function...”, is updated for a few reasons. First, wording improvements to relocate the cross reference to the end. Second, it is no longer, “particularly unique”, because, now that tuple
has been added, it also has several ways of being declared. The next sentence now says, “those types are atypical”. The cross-references to |vim9-func-declaration|
, |tuple-type|
, and |variadic-tuple|
conclude the paragraph.
*null-compare*
null
, null_<type>
, and empty
container. A re-structured example, building on what was in the original help, is provided. It echoes the results in tabular form. A further conceptual paragraph is included, since this is not a common structure, so some rationale (for why it is what it is) may be useful for those used to different null treatment.*null-anomalies*
The first paragraph is unchanged except “may chose”, which is fixed.
Much of *null_anomalies*
section already contained very good, complete examples, though a few needed expansion/clarification.
The null-<type>
section did not note that the point is covered in detail in the preceding section (i.e., *null-compare*
). That’s been made clear, and the example simplified.
The “uninitialized string” explanation was incomplete. It noted that 's1 == null' is “unexpected” but did not explain either why this behavior occurs or how it differs from other container types. Also, it only shows s2 is null_string
but doesn't show s1 is null_string
, which would reveal the important fact that an uninitialized string is the same instance as null_string
.
Also shown now is the crucial underlying implementation distinction: uninitialized strings being a null_string
container whereas other containers are empty containers. All these things are addressed in the rewritten explanations and examples.
The static list following “An uninitialized variable...” is transformed into a two informative, sourceable examples. The update also addresses what would be invalid syntax if the user tried to take the code and execute it (i.e., the current help has var f: func...
). That has been fixed, and an enum example is included now too.
The container variables example has been moved to below the NOTE regarding specialized variables to keep the note with the relevant content. The container variables example has been expanded to hammer home the distinction between empty {container} == null_ whereas empty {container} != null.
https://github.com/vim/vim/pull/18610
(2 files)
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.
- The line, "If a type is given where it is not expected you can get E1272 .", is removed. It appears this is not an error that ever occurs? (There is no evidence of it in
src/testdir
; perhaps it was intended, though never implemented? The only instance of it appearing in the source code is insrc/errors.h
,"E1272: Using type not in a script context: %s"
, but there are no test files for it. So, it could be reinstated, though should only be reverted if it really is a reachable error, preferably with a demonstrable example.
The function Test_misplaced_type() in the testdir/test_vim9_script.vim file tests for the E1272 error.
You can see the output of this test by running the following command:
:call term_dumpload('testdir/dumps/Test_misplaced_type.dump')
So this error code should not be removed.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.
So this error code should not be removed.
Thanks, that error code was driving me mad trying to find a way to replicate it. How's this for reverting (and also demonstrating) it?
*E1272*
If a type is used in a context where types are not expected you can get
E1272. For example: >
:vim9cmd echo islocked('x: string')
< Note: This must be executed from Vim's command line, not sourced.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.
So this error code should not be removed.
Thanks, that error code was driving me mad trying to find a way to replicate it. How's this for reverting (and also demonstrating) it?
*E1272* If a type is used in a context where types are not expected you can get E1272. For example: > :vim9cmd echo islocked('x: string') < Note: This must be executed from Vim's command line, not sourced.
Looks good to me.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.