diff --git a/doc/vim9.jax b/doc/vim9.jax index fd4409f99..b0e78f816 100644 --- a/doc/vim9.jax +++ b/doc/vim9.jax @@ -22,12 +22,13 @@ script の新しい文法と機能について書かれている。 ------------------------------------------------------------------------------ - NOTE: この vim9.txt ヘルプファイルでは、`vim9script` で始まる Vim9 script の - コードブロックは、Vim9 script の構文がハイライトされている。また、これ - らはソースとして実行できるため、実行して出力内容を確認できる。ソースと - して実行するには、`:'<,'>source` を使用する (|:source-range| を参照)。 - これは、|V| で行を視覚的に選択し、`:so` と入力することで実行できる。 - 例えば、以下の Vim9 script で試してみてほしい: >vim9 + NOTE: この vim9.txt ヘルプファイルでは、`vim9script` (および `vim9cmd` で始 + まる個々の行) で始まる Vim9 script のコードブロックは、Vim9 script の + 構文がハイライトされている。また、これらはソースとして実行できるため、 + 実行して出力内容を確認できる。ソースとして実行するには、`:'<,'>source` + を使用する (|:source-range| を参照)。これは、|V| で行を視覚的に選択し、 + `:so` と入力することで実行できる。例えば、以下の Vim9 script で試して + みてほしい: >vim9 vim9script echowindow "Welcome to Vim9 script!" @@ -63,7 +64,7 @@ Vim9 script の主な目的は劇的な性能の向上である。これは、 りのオーバーヘッドが必要になる。そのため、Vim9 script では、この辞書が使用でき なくなった。その他の違いは、エラーの処理方法など、より微細なものである。 -Vim9 script は以下の場所で使用することができる: +Vim9 script の構文、セマンティクス、および動作は以下に適用される: - コマンド `:def` で定義された関数の中 - コマンド `vim9script` で始まるスクリプトファイルの中 - 上記のコンテキストで定義された自動コマンド @@ -77,18 +78,76 @@ Vim9 script と旧来の Vim script を混在させることができる。古 直す必要はなく、以前と同じように動作する。高速化が必要なコードには、いくつかの `:def` 関数を使用するとよいだろう。 -:vim9[cmd] {cmd} *:vim9* *:vim9cmd* *E1164* - Vim9 script の構文とセマンティクスを使用して {cmd} を評価、実 - 行する。コマンドを入力する時や、旧来のスクリプトまたは関数内で - 便利である。 +:vim9[cmd] {cmd} *:vim9* *:vim9cmd* + Vim9 script の構文、セマンティクス、および動作を使用して {cmd} + を評価し、実行する。`:function` や旧来の Vim script 内でコマン + ドを入力するときに便利である。 + + 次の短い例は、旧来の Vim script コマンドと :vim9cmd (つまり + Vim9 script コンテキスト) が似ているように見えるものの、構文だ + けでなく意味や動作も異なる可能性があることを示している。 >vim + + call popup_notification('entrée'[5:] + \ ->str2list()->string(), #{time: 7000}) + vim9cmd popup_notification('entrée'[5 :] + ->str2list()->string(), {time: 7000}) +< + Notes: 1) 出力が異なる理由は、Vim9 script は文字インデックス + を使用するのに対し、旧来の Vim script はバイトイン + デックスを使用するためである。|vim9-string-index| + を参照。 + 2) 構文も異なる。Vim9 script では: + - "[5 :]" 内のスペースは必須である + (|vim9-white-space| を参照)。 + - "\" による行継続は必須ではない。 + - "#" (辞書キーを引用符で囲むのを避けるため) は必須 + ではなく、許可もされない - |#{}| を参照。 + + *E1164* + `:vim9cmd` は単独では実行できない。コマンドが後に続く必要があ + る。 + +:leg[acy] {cmd} *:leg* *:legacy* + {cmd} を旧来の Vim script の構文、意味、および動作を使用して + 評価および実行する。これは、Vim9 script または `:def` 関数での + み適用できる。上記のスクリプトと同等のスクリプトを使用する場合 + (出力が異なる理由については、スクリプトの注記を参照): >vim9 + + vim9script + # レガシーコンテキスト - つまり、これは [769, 101] のポップ + # アップを作成する + legacy call popup_notification('entrée'[5:] + \ ->str2list()->string(), #{time: 7000}) + # Vim9 script コンテキスト - これは [101] のポップアップを作 + # 成する + popup_notification('entrée'[5 :] + ->str2list()->string(), {time: 7000}) +< + Vim9 script のスクリプトローカル変数は、旧来の Vim script と同 + 様に、プリフィックスに "s:" を付けることで使用できる。この例 + は、構文の違いを示している。Vim9 script ではスクリプトローカル + 変数は "k" だが、旧来の Vim script では "s:k" である。 >vim9 + + vim9script + var k: string = "Okay" + echo k + legacy echo s:k +< *E1189* + `:legacy` はコンパイルされた Vim9 script の制御フローコンテキ + ストでは使用できない。例: >vim9 + + vim9script + def F_1189() + if v:version == 900 + # E1189: Cannot use :legacy with this command: endif + legacy endif + enddef + F_1189() +< *E1234* + `:legacy` は単独では使用できず、その後にコマンドを続ける必要が + ある。 -:leg[acy] {cmd} *:leg* *:legacy* *E1189* *E1234* - 旧来のスクリプト構文とセマンティクスを使用して {cmd} を評価、 - 実行する。Vim9 script または :def 関数内でのみ便利である。 - Note {cmd} は旧来の式構文で解析されるため、ローカル変数を使用 - できないことに注意。 -|52.6| の Vim9 script の例を参照。 ============================================================================== 2. 旧来の Vim script からの変更点 *vim9-differences* @@ -104,6 +163,7 @@ Vim9 script と :def 関数を使用するときに最も頻繁に遭遇する .. yourName .. ", how are you?" - 読みやすさを向上させるために、多くの場所で空白が必要である。 + |vim9-white-space| を参照。 - `:let` *E1126* を使用せずに値を代入し、`:var` を使用して変数を宣言する: > var count = 0 count += 3 @@ -231,7 +291,7 @@ Vim9 関数 ~ var d = {func: Legacy, value: 'text'} d.func() enddef -< *E1096* *E1174* *E1175* + 引数の型と戻り値の型を指定する必要がある。"any" 型を使用することができ、その場 合は旧来の関数と同様に実行時に型チェックが行われる。 *E1106* @@ -272,7 +332,7 @@ Vim9 script のスクリプトレベルで `:function` または `:def` を使 def ThisFunction() # スクリプトローカル def g:ThatFunction() # グローバル export def Function() # import および import autoload 用 -< *E1058* *E1075* +< *E1075* `:def` 関数内で `:function` または `:def` を使用してネストされた関数を指定し、 名前空間が指定されていない場合、このネストされた関数は定義されているコードブ ロックに対してローカルになる。文字列引数を持つ `function()` で使用することはで @@ -829,7 +889,7 @@ Notes: 空白 ~ - *E1004* *E1068* *E1069* *E1074* *E1127* *E1202* + *vim9-white-space* *E1004* *E1068* *E1069* *E1074* *E1127* *E1202* Vim9 script では空白の適切な使用を強制する。これはもう許可されていない: > var name=234 # エラー! var name= 234 # エラー! @@ -1218,6 +1278,7 @@ Note 認識されていないコマンドを "|" でつなぐと、その後の 式中で ++var や --var を使うことはまだサポートされていません。 + ============================================================================== 3. 新しいスタイルの関数 *fast-functions* @@ -1465,37 +1526,71 @@ Note スクリプトレベルにおいて、ループ変数はループの後で ============================================================================== 4. 型 *vim9-types* - *E1008* *E1009* *E1010* *E1012* - *E1013* *E1029* *E1030* -以下の組み込み型がサポートされています: - bool - number - float - string - blob - list<{type}> - dict<{type}> - object<{type}> - job - channel - tuple<{type}> - tuple<{type}, {type}, ...> - tuple<...list<{type}>> - tuple<{type}, ...list<{type}>> - func - func: {type} - func({type}, ...) - func({type}, ...): {type} + +対応する内部 |v:t_TYPE| 変数とともに表示される以下の型がサポートされている。 + + number |v:t_number| + string |v:t_string| + func |v:t_func| + func: {type} |v:t_func| + func({type}, ...) |v:t_func| + func({type}, ...): {type} |v:t_func| + list<{type}> |v:t_list| + dict<{type}> |v:t_dict| + float |v:t_float| + bool |v:t_bool| + none |v:t_none| + job |v:t_job| + channel |v:t_channel| + blob |v:t_blob| + class |v:t_class| + object |v:t_object| + typealias |v:t_typealias| + enum |v:t_enum| + enumvalue |v:t_enumvalue| + tuple<{type}> |v:t_tuple| + tuple<{type}, {type}, ...> |v:t_tuple| + tuple<...list<{type}>> |v:t_tuple| + tuple<{type}, ...list<{type}>> |v:t_tuple| void -これらの型は宣言において使えますが、いかなる単純値も実際に "void" 型を持つこと -はありません。void (例えば、戻り値のない関数) を使おうとするとエラーがでます。 -*E1031* *E1186* + *E1031* *E1186* +これらの型は宣言で使用できるが、単純な値は "void" 型を持つことはできない。void +を値として使用しようとするとエラーが発生する。例: >vim9 -配列型はありません。代わりに list<{type}> を使ってください。不変のリストに -対しては大量の細かいメモリを割り当てするのを避ける効率的な実装が使われます。 + vim9script + def NoReturnValue(): void + enddef + try + const X: any = NoReturnValue() + catch + echo v:exception # E1031: Cannot use void value + try + echo NoReturnValue() + catch + echo v:exception # E1186: Expression does not result in a ... + endtry + endtry +< *E1008* *E1009* *E1010* *E1012* +不正な宣言や型の不一致はエラーを引き起こす。以下は、E1008、E1009、E1010、E1012 +のエラーの例である: >vim9 + + vim9cmd var l: list + vim9cmd var l: list + vim9cmd var l: list = ['42'] +< +配列型はない。代わりに、リストまたはタプルを使用する。これらの型はリテラル (定 +数) にもなり得る。次の例では、[5, 6] はリストのリテラル、(7, ) はタプルのリテ +ラルである。エコーされたリストもリストのリテラルである: >vim9 + + vim9script + var l: list = [1, 2] + var t: tuple<...list> = (3, 4) + echo [l, t, [5, 6], (7, )] +< *tuple-type* -tuple 型は、多かれ少なかれ具体的な方法で宣言できる: +tuple 型は次の方法で宣言できる: > tuple |Number| 型の項目を 1 つ含む tuple tuple |Number| と |String| の 2 つの項目を含む tuple tuple |Number|、|Float| および |Boolean| 型の 3 つの @@ -1519,7 +1614,9 @@ tuple> |Number| 型の項目とそれに続く 0 個以 var myTuple: tuple<...list> = () < *vim9-func-declaration* *E1005* *E1007* -部分適用と関数は幾らかの方法で宣言することができます: + *vim9-partial-declaration* + *vim9-func-type* +関数 (または部分関数) は次の方法で宣言できる: func 任意の種類の関数参照。引数や戻り値への型チェッ クはない。 func: void 任意の数および型の引数で、戻り値はない。 @@ -1541,34 +1638,113 @@ func({type}, ?{type}, ...list<{type}>): {type} - 可変長引数のリストの型 - 戻り値の型 -もし戻り値の型が "void" なら、関数は値を返しません。 +戻り値の型が "void" の場合、関数は値を返さない。 -関数参照はそれが呼び出し側から見えない追加の引数および・あるいは辞書を保存して -いる場合、|Partial| にすることもできます。それらは同じように呼び出されるた -め、宣言も同じです。 +参照は |Partial| にすることもできる。この場合、追加の引数や辞書が格納されるが、 +これらは呼び出し元からは参照できない。これらは同じ方法で呼び出されるため、宣言 +も同じである。この対話型の例では、円の半径を入力すると、partial を使用して面積 +を小数点以下 2 桁で返す: >vim9 -`:type` を使ってカスタム型を定義できます: > - :type MyList list -ユーザー関数と似たように、後から追加される組み込み型との名前の衝突を避けるた -め、カスタム型は大文字から始まらなければなりません。 - -そしてクラスとインターフェイスも型として使えます: > - :class MyClass - :var mine: MyClass + vim9script + def CircleArea(pi: float, radius: float): float + return pi * radius->pow(2) + enddef + const AREA: func(float): float = CircleArea->function([3.14]) + const RADIUS: float = "Enter a radius value: "->input()->str2float() + echo $"\nThe area of a circle with a radius of {RADIUS} is " .. + $"{AREA(RADIUS)} (π to two d.p.)" +< + *vim9-typealias-type* +カスタム型 (|typealias|) は `:type` で定義できる。ユーザー関数と同様に、大文字 +で始める必要がある (これにより、現在または将来の組み込み型との名前の衝突を回避 +できる)。以下の例は、完全平方のリストを作成し、|type()| (14、typealias) +と|typename()| を報告する: >vim9 - :interface MyInterface - :var mine: MyInterface + vim9script + type Ln = list + final perfect_squares: Ln = [1, 4, 9, 16, 25] + echo "Typename (Ln): " .. + $"type() is {Ln->type()} and typename() is {Ln->typename()}" +< + *E1105* +typealias 自体は文字列に変換できない: >vim9 - :class MyTemplate - :var mine: MyTemplate - :var mine: MyTemplate + vim9script + type Ln = list + const FAILS: func = (): string => { + echo $"{Ln}" # E1105: Cannot convert typealias to string + } +< + *vim9-class-type* *vim9-interface-type* + *vim9-object-type* +|class|、|object|、|interface| はすべて型として使用できる。以下の対話型の例は、 +float 値の入力を促し、2 つの異なる図形の面積を返す。また、クラス、オブジェク +ト、インターフェイスの |type()| と |typename()| も報告する: >vim9 - :class MyInterface - :var mine: MyInterface - :var mine: MyInterface -{not implemented yet} + vim9script + interface Shape + def InfoArea(): tuple + endinterface + class Circle implements Shape + var radius: float + def InfoArea(): tuple + return ('Circle (π × r²)', 3.141593 * this.radius->pow(2)) + enddef + endclass + class Square implements Shape + var side: float + def InfoArea(): tuple + return ('Square (s²)', this.side->pow(2)) + enddef + endclass + const INPUT: float = "Enter a float value: "->input()->str2float() + echo "\nAreas of shapes:" + var myCircle: object = Circle.new(INPUT) + var mySquare: object = Square.new(INPUT) + final shapes: list = [myCircle, mySquare] + for shape in shapes + const [N: string, A: float] = shape.InfoArea() + echo $"\t- {N} has area of {A}" + endfor + echo "\n\t\ttype()\ttypename()\n\t\t------\t----------" + echo $"Circle\t\t{Circle->type()}\t{Circle->typename()}" + echo $"Square\t\t{Square->type()}\t{Square->typename()}" + echo $"Shape\t\t{Shape->type()}\t{Shape->typename()}" + echo $"MyCircle\t{myCircle->type()}\t{myCircle->typename()}" + echo $"MySquare\t{mySquare->type()}\t{mySquare->typename()}" + echo $"shapes\t\t{shapes->type()}\t{shapes->typename()}" +< + *vim9-enum-type* *vim9-enumvalue-type* +HEAST +An |enum| may be used as a type (|v:t_enum|). Variables holding enum values +have the enumvalue type (|v:t_enumvalue|) at runtime. The following +interactive example prompts for a character and returns information about +either a square or a rhombus. It also reports on the |type()| and |typename()| +of the enum and enumvalue: >vim9 + vim9script + enum Quad + Square('four', 'only'), + Rhombus('opposite', 'no') + var eq: string + var ra: string + def string(): string + return $"\nA {this.name} has " .. + $"{this.eq} equal sides and {this.ra} right angles\n\n" + enddef + endenum + echo "Rhombus (r) or Square (s)?" + var myQuad: Quad = getcharstr() =~ '\c^R' ? Quad.Rhombus : Quad.Square + echo myQuad.string() .. "\ttype()\ttypename()" + echo $"Quad \t{Quad->type()} \t{Quad->typename()}" + echo $"myQuad\t{myQuad->type()}\t{myQuad->typename()}" +< + Notes: This script uses builtin method "string()" (|object-string()|). + The typename() of Quad and myQuad are the same ("enum") + whereas the type() is distinguished (myQuad returns 16, + enumvalue, whereas Quad returns 15, enum). +HEAST 変数の型と型キャスト ~ *variable-types* Vim9 script か `:def` で定義される関数内で宣言された変数は明示的に示された型 diff --git a/en/vim9.txt b/en/vim9.txt index 7941b83ab..e7fa41de3 100644 --- a/en/vim9.txt +++ b/en/vim9.txt @@ -24,11 +24,12 @@ features in Vim9 script. ------------------------------------------------------------------------------ NOTE: In this vim9.txt help file, the Vim9 script code blocks beginning - with `vim9script` are Vim9 script syntax highlighted. Also, they are - sourceable, meaning you can run them to see what they output. To - source them, use `:'<,'>source` (see |:source-range|), which is done - by visually selecting the line(s) with |V| and typing `:so`. - For example, try it on the following Vim9 script: >vim9 + with `vim9script` (and individual lines starting with `vim9cmd`) are + Vim9 script syntax highlighted. Also, they are sourceable, meaning + you can run them to see what they output. To source them, use + `:'<,'>source` (see |:source-range|), which is done by visually + selecting the line(s) with |V| and typing `:so`. For example, try it + on the following Vim9 script: >vim9 vim9script echowindow "Welcome to Vim9 script!" @@ -63,7 +64,7 @@ dictionary adds quite a lot of overhead. In a Vim9 function this dictionary is not available. Other differences are more subtle, such as how errors are handled. -The Vim9 script syntax and semantics are used in: +Vim9 script syntax, semantics, and behavior apply in: - a function defined with the `:def` command - a script file where the first command is `vim9script` - an autocommand defined in the context of the above @@ -77,18 +78,72 @@ Vim9 script and legacy Vim script can be mixed. There is no requirement to rewrite old scripts, they keep working as before. You may want to use a few `:def` functions for code that needs to be fast. -:vim9[cmd] {cmd} *:vim9* *:vim9cmd* *E1164* - Evaluate and execute {cmd} using Vim9 script syntax and - semantics. Useful when typing a command and in a legacy - script or function. +:vim9[cmd] {cmd} *:vim9* *:vim9cmd* + Evaluate and execute {cmd} using Vim9 script syntax, + semantics, and behavior. Useful when typing a command, + in a `:function`, or a legacy Vim script. + + The following short example shows how a legacy Vim script + command and a :vim9cmd (so Vim9 script context) may appear + similar, though may differ not just syntactically, but also + semantically and behaviorally. >vim + + call popup_notification('entrée'[5:] + \ ->str2list()->string(), #{time: 7000}) + vim9cmd popup_notification('entrée'[5 :] + ->str2list()->string(), {time: 7000}) +< + Notes: 1) The reason for the different output is Vim9 script + uses character indexing whereas legacy Vim script + uses byte indexing - see |vim9-string-index|. + 2) Syntax is different too. In Vim9 script: + - The space in "[5 :]" is mandatory (see + |vim9-white-space|). + - Line continuation with "\" is not required. + - The "#" (to avoid putting quotes around dictionary + keys) is neither required nor allowed - see |#{}|. + + *E1164* + `:vim9cmd` cannot stand alone; it must be followed by a command. + +:leg[acy] {cmd} *:leg* *:legacy* + Evaluate and execute {cmd} using legacy Vim script syntax, + semantics, and behavior. It is only applicable in a Vim9 + script or a `:def` function. Using an equivalent script to + the one, above (see its notes for why the output differs): >vim9 + + vim9script + # Legacy context - so, this creates a popup with [769, 101] + legacy call popup_notification('entrée'[5:] + \ ->str2list()->string(), #{time: 7000}) + # Vim9 script context - so, this creates a pop up with [101] + popup_notification('entrée'[5 :] + ->str2list()->string(), {time: 7000}) +< + Vim9 script script-local variables may be used by prefixing + "s:", like in legacy Vim script. This example shows the + difference in syntax: "k" for the script-local variable in + Vim9 script, "s:k" in the legacy Vim script context. >vim9 + + vim9script + var k: string = "Okay" + echo k + legacy echo s:k +< *E1189* + Using `:legacy` is not allowed in compiled Vim9 script + control flow contexts. For example: >vim9 + + vim9script + def F_1189() + if v:version == 900 + # E1189: Cannot use :legacy with this command: endif + legacy endif + enddef + F_1189() +< *E1234* + `:legacy` cannot stand alone; it must be followed by a command. -:leg[acy] {cmd} *:leg* *:legacy* *E1189* *E1234* - Evaluate and execute {cmd} using legacy script syntax and - semantics. Only useful in a Vim9 script or a :def function. - Note that {cmd} cannot use local variables, since it is parsed - with legacy expression syntax. -See some examples of Vim9 script at |52.6|. ============================================================================== 2. Differences from legacy Vim script *vim9-differences* @@ -103,7 +158,8 @@ script and `:def` functions; details are below: echo "hello " .. yourName .. ", how are you?" -- White space is required in many places to improve readability. +- White space is required in many places to improve readability, + see |vim9-white-space|. - Assign values without `:let` *E1126* , declare variables with `:var`: > var count = 0 count += 3 @@ -231,7 +287,7 @@ You can call a legacy dict function though: > var d = {func: Legacy, value: 'text'} d.func() enddef -< *E1096* *E1174* *E1175* + The argument types and return type need to be specified. The "any" type can be used, type checking will then be done at runtime, like with legacy functions. @@ -274,7 +330,7 @@ script "export" needs to be used for those to be used elsewhere. > def ThisFunction() # script-local def g:ThatFunction() # global export def Function() # for import and import autoload -< *E1058* *E1075* +< *E1075* When using `:function` or `:def` to specify a nested function inside a `:def` function and no namespace was given, this nested function is local to the code block it is defined in. It cannot be used in `function()` with a string @@ -841,7 +897,7 @@ Notes: White space ~ - *E1004* *E1068* *E1069* *E1074* *E1127* *E1202* + *vim9-white-space* *E1004* *E1068* *E1069* *E1074* *E1127* *E1202* Vim9 script enforces proper use of white space. This is no longer allowed: > var name=234 # Error! var name= 234 # Error! @@ -1235,6 +1291,7 @@ subtracting one: > Using ++var or --var in an expression is not supported yet. + ============================================================================== 3. New style functions *fast-functions* @@ -1478,38 +1535,72 @@ without arguments. Example: > ============================================================================== 4. Types *vim9-types* - *E1008* *E1009* *E1010* *E1012* - *E1013* *E1029* *E1030* -The following builtin types are supported: - bool - number - float - string - blob - list<{type}> - dict<{type}> - object<{type}> - job - channel - tuple<{type}> - tuple<{type}, {type}, ...> - tuple<...list<{type}>> - tuple<{type}, ...list<{type}>> - func - func: {type} - func({type}, ...) - func({type}, ...): {type} + +The following types, each shown with its corresponding internal |v:t_TYPE| +variable, are supported: + + number |v:t_number| + string |v:t_string| + func |v:t_func| + func: {type} |v:t_func| + func({type}, ...) |v:t_func| + func({type}, ...): {type} |v:t_func| + list<{type}> |v:t_list| + dict<{type}> |v:t_dict| + float |v:t_float| + bool |v:t_bool| + none |v:t_none| + job |v:t_job| + channel |v:t_channel| + blob |v:t_blob| + class |v:t_class| + object |v:t_object| + typealias |v:t_typealias| + enum |v:t_enum| + enumvalue |v:t_enumvalue| + tuple<{type}> |v:t_tuple| + tuple<{type}, {type}, ...> |v:t_tuple| + tuple<...list<{type}>> |v:t_tuple| + tuple<{type}, ...list<{type}>> |v:t_tuple| void -These types can be used in declarations, but no simple value will actually -have the "void" type. Trying to use a void (e.g. a function without a -return value) results in error *E1031* *E1186* . + *E1031* *E1186* +These types can be used in declarations, though no simple value can have the +"void" type. Trying to use a void as a value results in an error. Examples: >vim9 -There is no array type, use list<{type}> instead. For a list constant an -efficient implementation is used that avoids allocating a lot of small pieces -of memory. + vim9script + def NoReturnValue(): void + enddef + try + const X: any = NoReturnValue() + catch + echo v:exception # E1031: Cannot use void value + try + echo NoReturnValue() + catch + echo v:exception # E1186: Expression does not result in a ... + endtry + endtry +< *E1008* *E1009* *E1010* *E1012* +Ill-formed declarations and mismatching types result in errors. The following +are examples of errors E1008, E1009, E1010, and E1012: >vim9 + + vim9cmd var l: list + vim9cmd var l: list + vim9cmd var l: list = ['42'] +< +There is no array type. Instead, use either a list or a tuple. Those types +may also be literals (constants). In the following example, [5, 6] is a list +literal and (7, ) a tuple literal. The echoed list is a list literal too: >vim9 + + vim9script + var l: list = [1, 2] + var t: tuple<...list> = (3, 4) + echo [l, t, [5, 6], (7, )] +< *tuple-type* -A tuple type can be declared in more or less specific ways: +A tuple type may be declared in the following ways: tuple a tuple with a single item of type |Number| tuple a tuple with two items of type |Number| and |String| @@ -1567,29 +1658,108 @@ If the return type is "void" the function does not return a value. The reference can also be a |Partial|, in which case it stores extra arguments and/or a dictionary, which are not visible to the caller. Since they are -called in the same way the declaration is the same. +called in the same way, the declaration is the same. This interactive example +prompts for a circle's radius and returns its area to two decimal places, +using a partial: >vim9 -Custom types can be defined with `:type`: > - :type MyList list -Custom types must start with a capital letter, to avoid name clashes with -builtin types added later, similarly to user functions. - -And classes and interfaces can be used as types: > - :class MyClass - :var mine: MyClass + vim9script + def CircleArea(pi: float, radius: float): float + return pi * radius->pow(2) + enddef + const AREA: func(float): float = CircleArea->function([3.14]) + const RADIUS: float = "Enter a radius value: "->input()->str2float() + echo $"\nThe area of a circle with a radius of {RADIUS} is " .. + $"{AREA(RADIUS)} (π to two d.p.)" +< + *vim9-typealias-type* +Custom types (|typealias|) can be defined with `:type`. They must start with +a capital letter (which avoids name clashes with either current or future +builtin types) similar to user functions. This example creates a list of +perfect squares and reports on |type()| (14, a typealias) and the |typename()|: >vim9 - :interface MyInterface - :var mine: MyInterface + vim9script + type Ln = list + final perfect_squares: Ln = [1, 4, 9, 16, 25] + echo "Typename (Ln): " .. + $"type() is {Ln->type()} and typename() is {Ln->typename()}" +< + *E1105* +A typealias itself cannot be converted to a string: >vim9 - :class MyTemplate - :var mine: MyTemplate - :var mine: MyTemplate + vim9script + type Ln = list + const FAILS: func = (): string => { + echo $"{Ln}" # E1105: Cannot convert typealias to string + } +< + *vim9-class-type* *vim9-interface-type* + *vim9-object-type* +A |class|, |object|, and |interface| may all be used as types. The following +interactive example prompts for a float value and returns the area of two +different shapes. It also reports on the |type()| and |typename()| of the +classes, objects, and interface: >vim9 - :class MyInterface - :var mine: MyInterface - :var mine: MyInterface -{not implemented yet} + vim9script + interface Shape + def InfoArea(): tuple + endinterface + class Circle implements Shape + var radius: float + def InfoArea(): tuple + return ('Circle (π × r²)', 3.141593 * this.radius->pow(2)) + enddef + endclass + class Square implements Shape + var side: float + def InfoArea(): tuple + return ('Square (s²)', this.side->pow(2)) + enddef + endclass + const INPUT: float = "Enter a float value: "->input()->str2float() + echo "\nAreas of shapes:" + var myCircle: object = Circle.new(INPUT) + var mySquare: object = Square.new(INPUT) + final shapes: list = [myCircle, mySquare] + for shape in shapes + const [N: string, A: float] = shape.InfoArea() + echo $"\t- {N} has area of {A}" + endfor + echo "\n\t\ttype()\ttypename()\n\t\t------\t----------" + echo $"Circle\t\t{Circle->type()}\t{Circle->typename()}" + echo $"Square\t\t{Square->type()}\t{Square->typename()}" + echo $"Shape\t\t{Shape->type()}\t{Shape->typename()}" + echo $"MyCircle\t{myCircle->type()}\t{myCircle->typename()}" + echo $"MySquare\t{mySquare->type()}\t{mySquare->typename()}" + echo $"shapes\t\t{shapes->type()}\t{shapes->typename()}" +< + *vim9-enum-type* *vim9-enumvalue-type* +An |enum| may be used as a type (|v:t_enum|). Variables holding enum values +have the enumvalue type (|v:t_enumvalue|) at runtime. The following +interactive example prompts for a character and returns information about +either a square or a rhombus. It also reports on the |type()| and |typename()| +of the enum and enumvalue: >vim9 + vim9script + enum Quad + Square('four', 'only'), + Rhombus('opposite', 'no') + var eq: string + var ra: string + def string(): string + return $"\nA {this.name} has " .. + $"{this.eq} equal sides and {this.ra} right angles\n\n" + enddef + endenum + echo "Rhombus (r) or Square (s)?" + var myQuad: Quad = getcharstr() =~ '\c^R' ? Quad.Rhombus : Quad.Square + echo myQuad.string() .. "\ttype()\ttypename()" + echo $"Quad \t{Quad->type()} \t{Quad->typename()}" + echo $"myQuad\t{myQuad->type()}\t{myQuad->typename()}" +< + Notes: This script uses builtin method "string()" (|object-string()|). + The typename() of Quad and myQuad are the same ("enum") + whereas the type() is distinguished (myQuad returns 16, + enumvalue, whereas Quad returns 15, enum). Variable types and type casting ~ *variable-types*