# HG changeset patch # User Christian Brabandt # Date 1703497503 -3600 # Node ID 681e2c008f83c74f2abc12e54fc468f725c88055 # Parent 34f6f3678cae78e253f73c14ebc185a130e2bd21 runtime(doc): Add variable categories and null related documentation(#13750) Commit: https://github.com/vim/vim/commit/cea3dac76e42c9a33dccbd2f10ef011f0be5c292 Author: errael Date: Mon Dec 25 01:31:23 2023 -0800 runtime(doc): Add variable categories and null related documentation(https://github.com/vim/vim/issues/13750) Signed-off-by: Ernie Rael Signed-off-by: Christian Brabandt diff --git a/runtime/doc/tags b/runtime/doc/tags --- 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 --- 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 w 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 # 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_ predefined +values, for example |null_string|, |null_list|, |null_job|. Primitives do not +have a null_. The typical use cases for null_ 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_ 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 + # ... add lots of stuff to list + l = [] # clear the variable and release container resources +Using the empty container, rather than null_, 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 # empty container + var l2: list = [] # empty container + var l3: list = 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" + var d2 = null_dict # type is "dict" + +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_ in a comparison: > + vim9script + def F(arg: list = 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 = 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_; 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_ 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 + var s2: list = 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_ 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_ is equal to the null_ 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 l != null *** + var d: dict 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_; but not null: + var s2: string = "" == null_string != null + var b2: blob = 0z == null_blob != null + var l2: list = [] == null_list != null + var d2: dict = {} == null_dict != null + +NOTE: the specialized variables, like job, default to null value and have no +corresponding empty value. + ============================================================================== 5. Namespace, Import and Export