Skip to content

Commit cea3dac

Browse files
authored
runtime(doc): Add variable categories and null related documentation(#13750)
Signed-off-by: Ernie Rael <errael@raelity.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent 9042bd8 commit cea3dac

2 files changed

Lines changed: 160 additions & 3 deletions

File tree

runtime/doc/tags

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9082,7 +9082,11 @@ notepad gui_w32.txt /*notepad*
90829082
nr2char() builtin.txt /*nr2char()*
90839083
nroff.vim syntax.txt /*nroff.vim*
90849084
null vim9.txt /*null*
9085+
null-anomalies vim9.txt /*null-anomalies*
9086+
null-compare vim9.txt /*null-compare*
9087+
null-details vim9.txt /*null-details*
90859088
null-variable eval.txt /*null-variable*
9089+
null-variables vim9.txt /*null-variables*
90869090
null_blob vim9.txt /*null_blob*
90879091
null_channel vim9.txt /*null_channel*
90889092
null_class vim9.txt /*null_class*
@@ -10945,6 +10949,7 @@ val-variable eval.txt /*val-variable*
1094510949
valgrind debug.txt /*valgrind*
1094610950
values() builtin.txt /*values()*
1094710951
var-functions usr_41.txt /*var-functions*
10952+
variable-categories vim9.txt /*variable-categories*
1094810953
variable-scope eval.txt /*variable-scope*
1094910954
variable-types vim9.txt /*variable-types*
1095010955
variables eval.txt /*variables*

runtime/doc/vim9.txt

Lines changed: 155 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*vim9.txt* For Vim version 9.0. Last change: 2023 Dec 09
1+
*vim9.txt* For Vim version 9.0. Last change: 2023 Dec 24
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1055,8 +1055,11 @@ variable, since they cannot be deleted with `:unlet`. E.g.: >
10551055
10561056
The values can also be useful as the default value for an argument: >
10571057
def MyFunc(b: blob = null_blob)
1058-
if b == null_blob
1059-
# b argument was not given
1058+
# Note: compare against null, not null_blob,
1059+
# to distinguish the default value from an empty blob.
1060+
if b == null
1061+
# b argument was not given
1062+
See |null-compare| for more information about testing against null.
10601063

10611064
It is possible to compare `null` with any value, this will not give a type
10621065
error. However, comparing `null` with a number, float or bool will always
@@ -1698,6 +1701,155 @@ argument type checking: >
16981701
Types are checked for most builtin functions to make it easier to spot
16991702
mistakes.
17001703

1704+
Categories of variables, defaults and null handling ~
1705+
*variable-categories* *null-variables*
1706+
There are categories of variables:
1707+
primitive number, float, boolean
1708+
container string, blob, list, dict
1709+
specialized function, job, channel, user-defined-object
1710+
1711+
When declaring a variable without an initializer, an explicit type must be
1712+
provided. Each category has different default initialization semantics. Here's
1713+
an example for each category: >
1714+
var num: number # primitives default to a 0 equivalent
1715+
var cont: list<string> # containers default to an empty container
1716+
var spec: job # specialized variables default to null
1717+
<
1718+
Vim does not have a familiar null value; it has various null_<type> predefined
1719+
values, for example |null_string|, |null_list|, |null_job|. Primitives do not
1720+
have a null_<type>. The typical use cases for null_<type> are:
1721+
- to `clear a variable` and release its resources;
1722+
- as a `default for a parameter` in a function definition, see |null-compare|.
1723+
1724+
For a specialized variable, like `job`, null_<type> is used to clear the
1725+
resources. For a container variable, resources can also be cleared by
1726+
assigning an empty container to the variable. For example: >
1727+
var j: job = job_start(...)
1728+
# ... job does its work
1729+
j = null_job # clear the variable and release the job's resources
1730+
1731+
var l: list<any>
1732+
# ... add lots of stuff to list
1733+
l = [] # clear the variable and release container resources
1734+
Using the empty container, rather than null_<type>, to clear a container
1735+
variable may avoid null complications as described in |null-anomalies|.
1736+
1737+
The initialization semantics of container variables and specialized variables
1738+
differ. An uninitialized container defaults to an empty container: >
1739+
var l1: list<string> # empty container
1740+
var l2: list<string> = [] # empty container
1741+
var l3: list<string> = null_list # null container
1742+
"l1" and "l2" are equivalent and indistinguishable initializations; but "l3"
1743+
is a null container. A null container is similar to, but different from, an
1744+
empty container, see |null-anomalies|.
1745+
1746+
Specialized variables default to null. These job initializations are
1747+
equivalent and indistinguishable: >
1748+
var j1: job
1749+
var j2: job = null_job
1750+
var j3 = null_job
1751+
1752+
When a list or dict is declared, if the item type is not specified and can not
1753+
be inferred, then the type is "any": >
1754+
var d1 = {} # type is "dict<any>"
1755+
var d2 = null_dict # type is "dict<any>"
1756+
1757+
Declaring a function, see |vim9-func-declaration|, is particularly unique.
1758+
1759+
*null-compare*
1760+
For familiar null compare semantics, where a null container is not equal to
1761+
an empty container, do not use null_<type> in a comparison: >
1762+
vim9script
1763+
def F(arg: list<string> = null_list)
1764+
if arg == null
1765+
echo "null"
1766+
else
1767+
echo printf("not null, %sempty", empty(arg) ? '' : 'not ')
1768+
endif
1769+
enddef
1770+
F() # output: "null"
1771+
F(null_list) # output: "null"
1772+
F([]) # output: "not null, empty"
1773+
F(['']) # output: "not null, not empty"
1774+
The above function takes a `list of strings` and reports on it.
1775+
Change the above function signature to accept different types of arguments: >
1776+
def F(arg: list<any> = null_list) # any type of list
1777+
def F(arg: any = null) # any type
1778+
<
1779+
In the above example, where the goal is to distinguish a null list from an
1780+
empty list, comparing against `null` instead of `null_list` is the correct
1781+
choice. The basic reason is because "null_list == null" and "[] != null".
1782+
Comparing to `null_list` fails since "[] == null_list". In the following section
1783+
there are details about comparison results.
1784+
1785+
*null-details* *null-anomalies*
1786+
This section describes issues about using null and null_<type>; included below
1787+
are the enumerated results of null comparisons. In some cases, if familiar
1788+
with vim9 null semantics, the programmer may chose to use null_<type> in
1789+
comparisons and/or other situations.
1790+
1791+
Elsewhere in the documentation it says:
1792+
Quite often a null value is handled the same as an
1793+
empty value, but not always
1794+
Here's an example: >
1795+
vim9script
1796+
var s1: list<string>
1797+
var s2: list<string> = null_list
1798+
echo s1 # output: "[]"
1799+
echo s2 # output: "[]"
1800+
1801+
echo s1 + ['a'] # output: "['a']"
1802+
echo s2 + ['a'] # output: "['a']"
1803+
1804+
echo s1->add('a') # output: "['a']"
1805+
echo s2->add('a') # E1130: Can not add to null list
1806+
<
1807+
Two values equal to a null_<type> are not necessarily equal to each other: >
1808+
vim9script
1809+
echo {} == null_dict # true
1810+
echo null_dict == null # true
1811+
echo {} == null # false
1812+
<
1813+
Unlike the other containers, an uninitialized string is equal to null. The
1814+
'is' operator can be used to determine if it is a null_string: >
1815+
vim9script
1816+
var s1: string
1817+
var s2 = null_string
1818+
echo s1 == null # true - this is unexpected
1819+
echo s2 == null # true
1820+
echo s2 is null_string # true
1821+
1822+
var b1: blob
1823+
var b2 = null_blob
1824+
echo b1 == null # false
1825+
echo b2 == null # true
1826+
<
1827+
Any variable initialized to the null_<type> is equal to the null_<type> and is
1828+
also equal to null. For example: >
1829+
vim9script
1830+
var x = null_blob
1831+
echo x == null_blob # true
1832+
echo x == null # true
1833+
<
1834+
An uninitialized variable is usually equal to null; it depends on its type:
1835+
var s: string s == null
1836+
var b: blob b != null ***
1837+
var l: list<any> l != null ***
1838+
var d: dict<any> d != null ***
1839+
var f: func f == null
1840+
var j: job j == null
1841+
var c: channel c == null
1842+
var o: Class o == null
1843+
1844+
A variable initialized to empty equals null_<type>; but not null:
1845+
var s2: string = "" == null_string != null
1846+
var b2: blob = 0z == null_blob != null
1847+
var l2: list<any> = [] == null_list != null
1848+
var d2: dict<any> = {} == null_dict != null
1849+
1850+
NOTE: the specialized variables, like job, default to null value and have no
1851+
corresponding empty value.
1852+
17011853
==============================================================================
17021854

17031855
5. Namespace, Import and Export

0 commit comments

Comments
 (0)