summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorerrael <errael@raelity.com>2023-12-25 01:31:23 -0800
committerGitHub <noreply@github.com>2023-12-25 10:31:23 +0100
commitcea3dac76e42c9a33dccbd2f10ef011f0be5c292 (patch)
treebc0ae0cd3517ade3da6086dea2605291b1bb112b /runtime
parent9042bd8b09bae0051fdf8eb5a57fa4b4420c92a0 (diff)
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>
Diffstat (limited to 'runtime')
-rw-r--r--runtime/doc/tags5
-rw-r--r--runtime/doc/vim9.txt158
2 files changed, 160 insertions, 3 deletions
diff --git a/runtime/doc/tags b/runtime/doc/tags
index 2ee7cede9d..ad92fcdfe6 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -9082,7 +9082,11 @@ notepad gui_w32.txt /*notepad*
nr2char() builtin.txt /*nr2char()*
nroff.vim syntax.txt /*nroff.vim*
null vim9.txt /*null*
+null-anomalies vim9.txt /*null-anomalies*
+null-compare vim9.txt /*null-compare*
+null-details vim9.txt /*null-details*
null-variable eval.txt /*null-variable*
+null-variables vim9.txt /*null-variables*
null_blob vim9.txt /*null_blob*
null_channel vim9.txt /*null_channel*
null_class vim9.txt /*null_class*
@@ -10945,6 +10949,7 @@ val-variable eval.txt /*val-variable*
valgrind debug.txt /*valgrind*
values() builtin.txt /*values()*
var-functions usr_41.txt /*var-functions*
+variable-categories vim9.txt /*variable-categories*
variable-scope eval.txt /*variable-scope*
variable-types vim9.txt /*variable-types*
variables eval.txt /*variables*
diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt
index 0f4ea17ec7..e7d0f2ae35 100644
--- a/runtime/doc/vim9.txt
+++ b/runtime/doc/vim9.txt
@@ -1,4 +1,4 @@
-*vim9.txt* For Vim version 9.0. Last change: 2023 Dec 09
+*vim9.txt* For Vim version 9.0. Last change: 2023 Dec 24
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1055,8 +1055,11 @@ variable, since they cannot be deleted with `:unlet`. E.g.: >
The values can also be useful as the default value for an argument: >
def MyFunc(b: blob = null_blob)
- if b == null_blob
- # b argument was not given
+ # Note: compare against null, not null_blob,
+ # to distinguish the default value from an empty blob.
+ if b == null
+ # b argument was not given
+See |null-compare| for more information about testing against null.
It is possible to compare `null` with any value, this will not give a type
error. However, comparing `null` with a number, float or bool will always
@@ -1698,6 +1701,155 @@ argument type checking: >
Types are checked for most builtin functions to make it easier to spot
mistakes.
+Categories of variables, defaults and null handling ~
+ *variable-categories* *null-variables*
+There are categories of variables:
+ primitive number, float, boolean
+ container string, blob, list, dict
+ specialized function, job, channel, user-defined-object
+
+When declaring a variable without an initializer, an explicit type must be
+provided. Each category has different default initialization semantics. Here's
+an example for each category: >
+ var num: number # primitives default to a 0 equivalent
+ var cont: list<string> # containers default to an empty container
+ var spec: job # specialized variables default to null
+<
+Vim does not have a familiar null value; it has various null_<type> predefined
+values, for example |null_string|, |null_list|, |null_job|. Primitives do not
+have a null_<type>. The typical use cases for null_<type> are:
+- to `clear a variable` and release its resources;
+- as a `default for a parameter` in a function definition, see |null-compare|.
+
+For a specialized variable, like `job`, null_<type> is used to clear the
+resources. For a container variable, resources can also be cleared by
+assigning an empty container to the variable. For example: >
+ var j: job = job_start(...)
+ # ... job does its work
+ j = null_job # clear the variable and release the job's resources
+
+ var l: list<any>
+ # ... add lots of stuff to list
+ l = [] # clear the variable and release container resources
+Using the empty container, rather than null_<type>, to clear a container
+variable may avoid null complications as described in |null-anomalies|.
+
+The initialization semantics of container variables and specialized variables
+differ. An uninitialized container defaults to an empty container: >
+ var l1: list<string> # empty container
+ var l2: list<string> = [] # empty container
+ var l3: list<string> = null_list # null container
+"l1" and "l2" are equivalent and indistinguishable initializations; but "l3"
+is a null container. A null container is similar to, but different from, an
+empty container, see |null-anomalies|.
+
+Specialized variables default to null. These job initializations are
+equivalent and indistinguishable: >
+ var j1: job
+ var j2: job = null_job
+ var j3 = null_job
+
+When a list or dict is declared, if the item type is not specified and can not
+be inferred, then the type is "any": >
+ var d1 = {} # type is "dict<any>"
+ var d2 = null_dict # type is "dict<any>"
+
+Declaring a function, see |vim9-func-declaration|, is particularly unique.
+
+ *null-compare*
+For familiar null compare semantics, where a null container is not equal to
+an empty container, do not use null_<type> in a comparison: >
+ vim9script
+ def F(arg: list<string> = null_list)
+ if arg == null
+ echo "null"
+ else
+ echo printf("not null, %sempty", empty(arg) ? '' : 'not ')
+ endif
+ enddef
+ F() # output: "null"
+ F(null_list) # output: "null"
+ F([]) # output: "not null, empty"
+ F(['']) # output: "not null, not empty"
+The above function takes a `list of strings` and reports on it.
+Change the above function signature to accept different types of arguments: >
+ def F(arg: list<any> = null_list) # any type of list
+ def F(arg: any = null) # any type
+<
+In the above example, where the goal is to distinguish a null list from an
+empty list, comparing against `null` instead of `null_list` is the correct
+choice. The basic reason is because "null_list == null" and "[] != null".
+Comparing to `null_list` fails since "[] == null_list". In the following section
+there are details about comparison results.
+
+ *null-details* *null-anomalies*
+This section describes issues about using null and null_<type>; included below
+are the enumerated results of null comparisons. In some cases, if familiar
+with vim9 null semantics, the programmer may chose to use null_<type> in
+comparisons and/or other situations.
+
+Elsewhere in the documentation it says:
+ Quite often a null value is handled the same as an
+ empty value, but not always
+Here's an example: >
+ vim9script
+ var s1: list<string>
+ var s2: list<string> = null_list
+ echo s1 # output: "[]"
+ echo s2 # output: "[]"
+
+ echo s1 + ['a'] # output: "['a']"
+ echo s2 + ['a'] # output: "['a']"
+
+ echo s1->add('a') # output: "['a']"
+ echo s2->add('a') # E1130: Can not add to null list
+<
+Two values equal to a null_<type> are not necessarily equal to each other: >
+ vim9script
+ echo {} == null_dict # true
+ echo null_dict == null # true
+ echo {} == null # false
+<
+Unlike the other containers, an uninitialized string is equal to null. The
+'is' operator can be used to determine if it is a null_string: >
+ vim9script
+ var s1: string
+ var s2 = null_string
+ echo s1 == null # true - this is unexpected
+ echo s2 == null # true
+ echo s2 is null_string # true
+
+ var b1: blob
+ var b2 = null_blob
+ echo b1 == null # false
+ echo b2 == null # true
+<
+Any variable initialized to the null_<type> is equal to the null_<type> and is
+also equal to null. For example: >
+ vim9script
+ var x = null_blob
+ echo x == null_blob # true
+ echo x == null # true
+<
+An uninitialized variable is usually equal to null; it depends on its type:
+ var s: string s == null
+ var b: blob b != null ***
+ var l: list<any> l != null ***
+ var d: dict<any> d != null ***
+ var f: func f == null
+ var j: job j == null
+ var c: channel c == null
+ var o: Class o == null
+
+A variable initialized to empty equals null_<type>; but not null:
+ var s2: string = "" == null_string != null
+ var b2: blob = 0z == null_blob != null
+ var l2: list<any> = [] == null_list != null
+ var d2: dict<any> = {} == null_dict != null
+
+NOTE: the specialized variables, like job, default to null value and have no
+corresponding empty value.
+
==============================================================================
5. Namespace, Import and Export