]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
runtime(doc): Add variable categories and null related documentation(#13750)
authorerrael <errael@raelity.com>
Mon, 25 Dec 2023 09:31:23 +0000 (01:31 -0800)
committerGitHub <noreply@github.com>
Mon, 25 Dec 2023 09:31:23 +0000 (10:31 +0100)
Signed-off-by: Ernie Rael <errael@raelity.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/doc/tags
runtime/doc/vim9.txt

index 2ee7cede9d5d5c44c072b975cd5ac3e6d6fece20..ad92fcdfe6761aa62a1338dfaf4e2fca44a0d87f 100644 (file)
@@ -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*
index 0f4ea17ec7a67feb81311758ce395d8d9d1487d3..e7d0f2ae353e44f18a4dc4628333b4971a6d0e4e 100644 (file)
@@ -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