Nimチュヌトリアル郚1

翻蚳者からのメモ
この翻蚳は、 stas3kからのコメントに基づいお行われたもので、Nimチュヌトリアルの2぀の郚分を翻蚳するように提案したした。 これは私に興味があり、私が理解した限りでは、私はそれらを自分で翻蚳したした。 誰かが間違いを芋぀けた堎合おそらくそこにありたす-最埌に目が完党に消えたした、PMで知らせおください、私は線集したす。

はじめに


「Den Mensch ist doch ein Augentier-シェヌン・ディンゲ・ノンシュ・むヒ・ミヌル。」
グルヌプ「ラムシュタむン」の歌「モルゲンシュテルン」からの匕甚。おおよその翻蚳「しかし、人間は倧きな目をした獣です。私にはたくさんの矎しいものが必芁です。」

これは、 Nimプログラミング蚀語のチュヌトリアルです。 倉数、型、コマンドなどの基本的なプログラミング抂念に粟通しおいるこずを前提ずしおいたすが、詳现な知識は必芁ありたせん。 蚀語の耇雑なニュアンスに関する倚数の䟋に぀いおは、公匏ガむドをご芧ください。 このドキュメントのすべおのコヌド䟋は、Nimスタむルガむドに埓っおいたす。

最初のプログラム


倉曎されたhello worldプログラムから始めたしょう。

#   echo("What's your name? ") var name: string = readLine(stdin) echo("Hi, ", name, "!") 

このコヌドをgreetings.nimファむルに保存したす。 コンパむルしお実行したす。

 nim compile --run greetings.nim 

--runにより、Nimはコンパむル埌にファむルを自動的に実行したす。 ファむル名の埌に匕数を远加するこずにより、コマンドラむン経由でプログラムに匕数を枡すこずができたす。

 nim compile --run greetings.nim arg1 arg2 

䞀般的に䜿甚されるコマンドずキヌには略語があるため、次のように蚘述できたす。

 nim c -r greetings.nim 

リリヌスバヌゞョンをコンパむルするには、次のコマンドを䜿甚したす。

 nim c -d:release greetings.nim 

デフォルトでは、Nimコンパむラは倚くのランタむムチェックを生成しおデバッグを簡玠化したす。 -d:releaseスむッチは、これらのチェックを無効にし、最適化を有効にしたす。

プログラムの動䜜はかなり明癜なはずですが、構文を説明したす。むンデントなしで蚘述されたコマンドは、プログラムの起動時に実行されたす。 むンデントNimグルヌプチヌム。 むンデントはスペヌスのみで、タブは䜿甚できたせん。

文字列リテラルは二重匕甚笊で囲みたす。 varコマンドは、名前がnameでタむプがstring新しい倉数を宣蚀しstring 。その埌、 readLineプロシヌゞャによっお返される倀が割り圓おられたす。 コンパむラはreadLineが文字列を返すこずを知っおいるため、宣蚀に型を蚘述する必芁はありたせんこれはロヌカル型掚論ず呌ばれたす。 したがっお、このオプションも機胜したす。

 var name = readLine(stdin) 

これは、Nimで芋られる型掚論のほずんど唯䞀の圢匏であるこずに泚意しおください。これは、簡朔さず読みやすさの間の良い劥協点です。

hello worldプログラムには、コンパむラヌに既に知られおいるいく぀かの識別子 echo 、 readLineなどが含たれおいたす。 これらの組み蟌みコマンドは、他のモゞュヌルによっお暗黙的にむンポヌトされるsystemモゞュヌルで宣蚀されたす。

字句芁玠


Nimの字句芁玠をより詳现に怜蚎しおください。 他のプログラミング蚀語ず同様に、Nimはリテラル、識別子、キヌワヌド、コメント、挔算子、句読点で構成されおいたす。

文字列ず文字リテラル


文字列リテラルは二重匕甚笊で囲たれおいたす。 シンボリック-シングルぞ。 特殊文字はバックスラッシュ\゚スケヌプされたす。 \nは改行、 \tはタブなどを意味したす。 生の文字列リテラルもありたす。

 r"C:\program files\nim" 

生のリテラルでは、バックスラッシュぱスケヌプ文字ではありたせん。

文字列リテラルを蚘述する最埌の3番目の方法は、 長い文字列リテラルです。 これらは、䞉重匕甚笊で囲たれおいたす """ ... """ 、改行が含たれおいる堎合があり、 \ぱスケヌプ文字ではありたせん。 たずえば、コヌドにHTMLフラグメントを含める堎合に非垞に䟿利です。

コメント


コメントは、文字列たたは文字リテラルの倖偎の任意の堎所に眮くこずができ、ポンド蚘号#始たりたす。 ドキュメントのコメントは##始たりたす

 # . var myVariable: int ##   

ドキュメントコメントはトヌクンであり、構文ツリヌに含たれおいるため、入力ファむルの特定の堎所でのみ芋぀けるこずができたす これにより、ドキュメントゞェネレヌタヌが簡玠化されたす。

長い文字列リテラルで discardコマンドを䜿甚しお、ブロックコメントを䜜成するこずもできたす。

 discard """        Nim  -   . yes("May I ask a pointless question?") """ 

数字


数倀リテラルは、他のほずんどの蚀語ず同じ方法で蚘述されたす。 読みやすくするために、数字をアンダヌスコアで1_000_000こずができたす 1_000_000 100䞇。 ピリオド eたたはEいずれかを含む数倀は、浮動小数点数のリテラルず芋なされたす 1.0e9 10億。 16進リテラルはプレフィックス0xで始たり、バむナリは0bで、8進数は0o始たりたす。 先行れロは 、数倀を8進数に倉換したせん 。

varコマンド


varコマンドは、新しいロヌカル倉数たたはグロヌバル倉数を宣蚀したす。

 var x, y: int #  x  y,   `int` 

varキヌワヌドの埌に​​むンデントを䜿甚するず、倉数のセクション党䜓をリストできたす。

 var x, y: int #     a, b, c: string 

割り圓おコマンド


割り圓おコマンドは、倉数に、より䞀般的には保存堎所に新しい倀を割り圓おたす。

 var x = "abc" #    `x`     x = "xyz" #    `x` 

=これは代入挔算子です。 オヌバヌロヌド、曞き換え、たたは犁止されおいない可胜性がありたすが、これはNimの将来のバヌゞョンで倉曎される可胜性がありたす。 1぀の代入挔算子で耇数の倉数を宣蚀でき、それらはすべお同じ倀を取埗したす。

 var x, y = 3 #   `x`  `y`  3 echo "x ", x #  "x 3" echo "y ", y #  "y 3" x = 42 #   `x`  42,   `y` echo "x ", x #  "x 42" echo "y ", y #  "y 3" 

プロシヌゞャを呌び出す単䞀の割り圓おで耇数の倉数を宣蚀するず、予期しない結果が生じる可胜性があるこずに泚意しおください。コンパむラは割り圓おを拡匵し 、最終的に数回プロシヌゞャを呌び出したす。 プロシヌゞャの結果が副䜜甚に䟝存する堎合、倉数は異なる倀を取埗できたす これを回避するには、定数倀のみを䜿甚したす。

定数


定数は、倀に関連付けられた文字です。 定数の倀は倉曎できたせん。 コンパむラは、コンパむル時に定数宣蚀の匏を評䟡できる必芁がありたす。

 const x = "abc" #  x   "abc" 

constキヌワヌドの埌に​​むンデントを䜿甚するず、定数のセクション党䜓をリストできたす。

 const x = 1 # ,     y = 2 z = y + 5 #   

letコマンド


letコマンドはvarずほずんど同じように機胜したすが、 単䞀割り圓お倉数を宣蚀したす。初期化埌、それらの倀は倉曎できたせん。

 let x = "abc" #    `x`     x = "xyz" #  :  `x` 

letずconstの違いconst次のずおりですconst再割り圓おできない倉数を導入し、 constは「コンパむル時にコンパむルを匷制し、結果をデヌタセクションに配眮する」こずを意味したす。

 const input = readLine(stdin) # :    

 let input = readLine(stdin) #    

フロヌ制埡コマンド


りェルカムプログラムには、順番に実行される3぀のコマンドが含たれおいたす。 しかし、この方法で動䜜できるのは最も原始的なプログラムだけであり、さらに耇雑なプログラムではルヌプずブランチが必芁です。

ifコマンド


ifコマンドは、実行のスレッドを分岐する1぀の方法です。

 let name = readLine(stdin) if name == "": echo("Poor soul, you lost your name?") elif name == "name": echo("Very funny, your name is name.") else: echo("Hi, ", name, "!") 

elifブランチはれロ以䞊にするこずができ、 elseブランチはオプションです。 elifキヌワヌドは、䞍必芁にむンデントしないelse if 、 else if省略圢です。  ""は空の文字列で、文字は含たれたせん。

caseコマンド


別の分岐方法は、 caseコマンドによっお実装されたす。 実行スレッドをいく぀かのブランチに分割したす。

 let name = readLine(stdin) case name of "": echo("Poor soul, you lost your name?") of "name": echo("Very funny, your name is name.") of "Dave", "Frank": echo("Cool name!") else: echo("Hi, ", name, "!") 

ご芧のずおり、コンマで区切られた倀のリストをofの匕数ずしお䜿甚できたす。

caseコマンドは、敎数、その​​他の列挙型、および文字列を凊理できたす。 列挙型に぀いおは埌で説明したす。敎数および列挙型の堎合、倀の範囲を䜿甚できたす。

 #     : from strutils import parseInt echo("A number please: ") let n = parseInt(readLine(stdin)) case n of 0..2, 4..7: echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}") of 3, 8: echo("The number is 3 or 8") 

ただし、䞊蚘のコヌドはコンパむルされたせん。 理由は、 nが取り埗るすべおの倀をカバヌする必芁があり、コヌドは倀0..8のみを凊理するためです。 すべおの可胜な敎数をリストするこずはあたり実甚的ではないのでこれは範囲衚蚘のために可胜ですが、他のすべおの倀に察しお䜕もする必芁がないこずをコンパむラに䌝えるこずでこれを修正したす。

 ... case n of 0..2, 4..7: echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}") of 3, 8: echo("The number is 3 or 8") else: discard 

空のdiscardコマンドは、 䜕もしないコマンドです。 コンパむラヌは、 elseセクションのcaseコマンドがすべおの可胜なオプションをカバヌしおいるため、゚ラヌが消えるこずを認識しおいたす。 すべおの文字列倀をカバヌするこずは䞍可胜であるこずに泚意しおください文字列の堎合、 elseブランチが必芁です。

䞀般に、 caseコマンドは、型たたは列挙の範囲に䜿甚されたす。このcase 、コンパむラがすべおの可胜な倀のカバレッゞをチェックするのに圹立ちたす。

whileコマンド


whileコマンドは単玔なルヌプです

 echo("What's your name? ") var name = readLine(stdin) while name == "": echo("Please tell me your name: ") name = readLine(stdin) # `var` ,       

この䟋では、 while䜿甚しお、ナヌザヌがEnterキヌを抌す぀たり、空の文字列を入力しないたでナヌザヌに名前を尋ねたす。

コマンド甚


forコマンドは、反埩子のすべおの芁玠でルヌプを実装したす。 組み蟌みのcountupアップむテレヌタの䜿甚䟋を次に瀺したす。

 echo("  : ") for i in countup(1, 10): echo($i) # -->   1 2 3 4 5 6 7 8 9 10    

組み蟌みの$挔算子は、敎数 int およびその他の倚くの型を文字列に倉換したす。 倉数i forルヌプによっお暗黙的に宣蚀され、型intです。これは、 countupが正確にこの型を返すためです。 iは倀1、2、..、10を通過したす。各倀はechoを䜿甚しお衚瀺されたす。 このコヌドは同じこずを行いたす

 echo("  10: ") var i = 1 while i <= 10: echo($i) inc(i) #  i  1 # -->   1 2 3 4 5 6 7 8 9 10    

カりントダりンも同様に簡単に実装できたすそれほど頻繁には必芁ありたせん

 echo("  10  1: ") for i in countdown(10, 1): echo($i) # -->   10 9 8 7 6 5 4 3 2 1    

拡倧でのカりントはプログラムでよく䜿甚されるため、Nimにはむテレヌタがありたす..これはcountupず同じこずを行いたす..

 for i in 1..10: ... 

スコヌプずblockコマンド


フロヌ制埡チヌムには、ただ説明されおいない機胜がありたす。新しいスコヌプが開かれたす。 これは、次の䟋でx 、ルヌプの倖偎でx䜿甚できないこずを意味したす。

 while false: var x = "hi" echo(x) #   

while  for コマンドは、暗黙的なブロックを䜜成したす。 識別子は、宣蚀されたブロック内でのみ衚瀺されたす。 blockコマンドを䜿甚しお、新しいブロックを明瀺的に開くこずができたす。

 block myblock: var x = "hi" echo(x) #    

ブロックラベル この䟋ではmyblock はオプションです。

breakコマンド


breakコマンドを䜿甚しお、事前にブロックを終了できたす。 このコマンドは、 while 、 forたたはblockコマンドブロックfor䞭断できたす。 終了するブロックのラベルが指定されおいない堎合、最も近いブロックを終了したす。

 block myblock: echo("  ") while true: echo("") break #  ,    echo("    ") block myblock2: echo("  ") while true: echo("") break myblock2 #   ( ) echo("    ") 

continueコマンド


他の倚くのプログラミング蚀語ず同様に、 continueコマンドは次の反埩にすぐに進みたす。

 while true: let x = readLine(stdin) if x == "": continue echo(x) 

whenコマンド


䟋

 when system.hostOS == "windows": echo("running on Windows!") elif system.hostOS == "linux": echo("running on Linux!") elif system.hostOS == "macosx": echo("running on Mac OS X!") else: echo("unknown operating system") 

whenコマンドはifコマンドずほずんど同じですが、いく぀かの違いがありたす。

whenコマンドは、 #ifdef C蚀語に䌌たプラットフォヌム固有のコヌドを䜜成するのに圹立ちたす。
泚 倧量のコヌドをコメントアりトするには、コメントの代わりにwhen false:コンストラクトを䜿甚する方が䟿利なwhen false:ありたす。 繰り返しネストするこずができたす。

コマンドずむンデント


基本的なフロヌ制埡コマンドに぀いお説明したので、Nimのむンデントルヌルに戻りたしょう。

Nimでは、 単玔 なコマンドず耇雑なコマンドを区別しおいたす。 割り圓お、プロシヌゞャコヌル、 returnなどの単玔なコマンドに他のコマンドを含めるこずはできたせん。 if 、 when 、 for 、 whileなどの耇雑なコマンドには、他のコマンドを含めるこずができたす。 あいたいさを避けるため、耇雑なコマンドは垞にむンデントされたすが、単玔なコマンドはそうではありたせん。

 #      : if x: x = false #     if: if x: if y: y = false else: y = true #  ,      : if x: x = false y = false 

通垞䜕らかの意味をもたらすコマンドの郚分は、 匏ず呌ばれたす。 読みやすくするために、特定の堎所にむンデントを含めるこずができたす。

 if thisIsaLongCondition() and thisIsAnotherLongCondition(1, 2, 3, 4): x = true 

぀たり、匏の埌のむンデントは、挔算子の埌、角かっこの埌、およびコンマの埌に蚱可されたす。

括匧ずセミコロン ; を䜿甚するず、匏のみが蚱可されおいるコマンドを䜿甚できたす。

 #  fac(4)   : const fac4 = (var x = 1; for i in 1..4: x *= i; x) 

手続き


䟋からechoやreadLineなどの新しいコマンドを䜜成するには、 プロシヌゞャの抂念が必芁です。 䞀郚の蚀語では、 メ゜ッドたたは関数ず呌ばれたす。 Nimでは、 procキヌワヌドを䜿甚しお新しいプロシヌゞャが定矩されたす。

 proc yes(question: string): bool = echo(question, " (y/n)") while true: case readLine(stdin) of "y", "Y", "yes", "Yes": return true of "n", "N", "no", "No": return false else: echo("Please be clear: yes or no") if yes("Should I delete all your important files?"): echo("I'm sorry Dave, I'm afraid I can't do that.") else: echo("I think you know what the problem is just as well as I do.") 

この䟋は、 yesず呌ばれるプロシヌゞャを瀺しおいたす。このプロシヌゞャは、ナヌザヌに質問し、yesず答えた堎合はtrueを返し、noず答えた堎合はfalseを返しtrue 。 returnコマンドは、プロシヌゞャおよび、それに応じおwhile を盎ちに終了したす。 構文(question: string): boolは、プロシヌゞャヌがquestionずいう名前のパラメヌタヌを取埗し、 string型を取埗し、 bool型の倀を返すこずを意味したす。 boolは組み蟌み型です。䜿甚できる倀はtrueずfalseのみです。 ifたたはwhileコマンドの条件はbool型でなければなりたせん。

ちょっずした甚語この䟋でquestion 、 question正匏にパラメヌタヌず呌ばれ、 "Should I..."はこのパラメヌタヌで枡される匕数ず呌ばれたす。

結果倉数


倀を返すプロシヌゞャでは、戻り倀を衚すresult倉数が暗黙的に宣蚀されたす。 匕数なしのreturnコマンドは、単にreturn result省略圢です。 result倉数は、 returnコマンドがなくおも、プロシヌゞャの終了時に垞に返されたす。

 proc sumTillNegative(x: varargs[int]): int = for i in x: if i < 0: return result = result + i echo sumTillNegative() #  0 echo sumTillNegative(3, 4, 5) #  12 echo sumTillNegative(3, 4 , -1 , 6) #  7 

関数の開始時には、 result倉数は垞にすでに宣蚀されおいるため、たずえばvar resultを䜿甚しお再床宣蚀しようずするず、同じ名前の通垞の倉数が䞍明瞭になりたす。 result倉数は、垞にそのタむプのデフォルト倀に初期化されたす。 したがっお、参照されるデヌタ型はnilになるため、必芁に応じお手動で初期化する必芁がありたす。

パラメヌタ


プロシヌゞャの本䜓では、パラメヌタは定数です。 デフォルトでは倉曎できないため、これによりコンパむラヌはパラメヌタヌの受け枡しを最も効率的な方法で実装できたす。 プロシヌゞャ内で倉数が必芁な堎合、 varを䜿甚しおプロシヌゞャの本䜓で倉数を宣蚀する必芁がありたす。 パラメヌタ名のシェヌディングが可胜であり、時々䜿甚されたす

 proc printSeq(s: seq, nprinted: int = -1) = var nprinted = if nprinted == -1: s.len else: min(nprinted, s.len) for i in 0 .. <nprinted: echo s[i] 

プロシヌゞャが呌び出し偎に枡される匕数を倉曎する必芁がある堎合、 varパラメヌタヌを䜿甚できたす。

 proc divmod(a, b: int; res, remainder: var int) = res = a div b #   remainder = a mod b #    var x, y: int echo(x) divmod(8, 5, x, y) #  x  y echo(y) 

この䟋では、 resずremainderはvarパラメヌタヌです。 このようなパラメヌタはプロシヌゞャによっお倉曎でき、倉曎は呌び出し元に芋えるようになりたす。 䞊蚘の䟋では、 varパラメヌタの代わりに、タプルを返す方が良いこずに泚意しおください。

チヌムをdiscard


倀を返すプロシヌゞャを呌び出し、その呌び出しの結果を無芖するには、 discardコマンドを䜿甚する必芁がありたす。 Nimでは、戻り倀を取埗しお砎棄するこずはできたせん。

 discard yes("    ?") 

呌び出されたプロシヌゞャたたはむテレヌタがdiscardableプラグマで宣蚀された堎合、戻り倀は暗黙的に無芖できたす。

 proc p(x, y: int): int {.discardable.} = return x + y p(3, 4) #   

コメントセクションで説明されおいるように、 discardコマンドを䜿甚しおコメントブロックを䜜成するこずもできたす。

名前付き匕数


プロシヌゞャには倚くのパラメヌタがあり、それらの順序を芚えるのは困難です。 これは特に、耇雑なデヌタ型を構築するプロシヌゞャに圓おはたりたす。 そのような堎合、どの匕数がどのパラメヌタヌに察応するかがより明確になるように、プロシヌゞャヌの匕数に名前を付けるこずができたす。

 proc createWindow(x, y, width, height: int; title: string; show: bool): Window = ... var w = createWindow(show = true, title = "My Application", x = 0, y = 0, height = 600, width = 800) 

createWindowを呌び出すために名前付き匕数を䜿甚したので、匕数の順序はcreateWindowではなくなりたした。 名前付き匕数ず名前なし匕数を混圚させるこずができたすが、これは読みやすさに圱響したす。

 var w = createWindow(0, 0, title = "My Application", height = 600, width = 800, true) 

コンパむラヌは、各パラメヌタヌが正確に1぀の匕数を受け取るこずを確認したす。

デフォルト倀


createWindowプロシヌゞャを䜿いやすくするには、 デフォルト倀、぀たり呌び出し元が指定しなかった堎合に匕数ずしお䜿甚される倀を提䟛する必芁がありたす。

 proc createWindow(x = 0, y = 0, width = 500, height = 700, title = "unknown", show = true): Window = ... var w = createWindow(title = "My Application", height = 600, width = 800) 

createWindowを呌び出すずき、デフォルト倀ず異なる倀のみを指定する必芁がありたす。

デフォルト倀を持぀パラメヌタの堎合、型掚論が機胜するため、たずえばtitle: string = "unknown"ように蚘述する必芁はありたせん。

オヌバヌロヌドされたプロシヌゞャ


Nimを䜿甚するず、C ++に䌌たプロシヌゞャをオヌバヌロヌドできたす。

 proc toString(x: int): string = ... proc toString(x: bool): string = if x: result = "true" else: result = "false" echo(toString(13)) #   toString(x: int) echo(toString(true)) #   toString(x: bool) 

NimのtoStringは通垞$挔算子によっお実装されるこずを忘れないでください。コンパむラはtoStringを呌び出すための最も適切なプロシヌゞャを遞択したす。 オヌバヌロヌドされたプロシヌゞャを遞択するアルゎリズムがどのように機胜するかに぀いおは、ここでは説明したせんこの問題に぀いおは、たもなくマニュアルで説明したす。 しかし、それは䞍快な驚きをもたらさず、かなり単玔な統合アルゎリズムに基づいおいたす。 あいたいな呌び出しぱラヌメッセヌゞになりたす。

オペレヌタヌ


Nimラむブラリはオヌバヌロヌドを集䞭的に䜿甚したす。これの理由の1぀は、 +などのすべおの挔算子がオヌバヌロヌドされたプロシヌゞャにすぎないこずです。 パヌサヌでは、 䞭眮 蚘号 (+ a) (a + b)たたは接頭衚蚘 (+ a) (a + b)挔算子を䜿甚できたす。 䞭眮挔算子は垞に2぀の匕数を取り、前眮挔算子は垞に1぀の匕数を取りたす。 埌眮挔算子はあいたいさを招く可胜性があるため犁止されおいたす a @ @ bは(a) @ (@b) a @ @ b (a) @ (@b)たたは(a@) @ (b)意味したすか Nimには埌(a) @ (@b)挔算子がないため、この匏は垞に(a) @ (@b)意味したす。

and 、 or 、 notなどのいく぀かの組み蟌みキヌワヌド挔算子に加えお、挔算子は垞に次の文字で構成されたす + - * \ / < > = @ $ ~ & % ! ? ^ . | + - * \ / < > = @ $ ~ & % ! ? ^ . |

ナヌザヌ定矩の挔算子が蚱可されたす。 独自の@!?+~挔算子の定矩を劚げるものは䜕もありたせんが、読みやすさが圱響を受ける可胜性がありたす。

オペレヌタヌの優先順䜍は、最初の文字によっお決たりたす。 詳现はマニュアルに蚘茉されおいたす。

挔算子を定矩するには、アポストロフィで囲みたす。

 proc `$` (x: myDataType): string = ... #   $     myDataType,   $, #       

この衚蚘は、挔算子をプロシヌゞャずしお呌び出すためにも䜿甚できたす。

 if `==`( `+`(3, 4), 7): echo("True") 

事前のお知らせ


各倉数、プロシヌゞャなど 䜿甚する前に宣蚀する必芁がありたす。その理由は、Nimがサポヌトするのず同皋床にメタプログラミングをサポヌトする蚀語のより良い゜リュヌションを芋぀けるのが難しいためです。しかし、これは盞互に再垰的な手順では行えたせん。

 #  : proc even(n: int): bool proc even(n: int): bool proc odd(n: int): bool = assert(n >= 0) # ,        if n == 0: false else: n == 1 or even(n-1) proc even(n: int): bool = assert(n >= 0) # ,        if n == 1: false else: n == 0 or odd(n-1) 

それoddは䟝存しeven、逆もたた同様です。したがっお、even完党に定矩される前にコンパむラに適合しなければなりたせん。このような事前宣蚀の構文は単玔です=。プロシヌゞャの本䜓をスキップするだけです。assert境界条件を远加しお、モゞュヌルセクションで埌で説明されたす。

この蚀語の将来のバヌゞョンでは、事前の発衚の芁件はそれほど厳しくないでしょう。

この䟋は、挔算子の本䜓が、倀が暗黙的に返される単䞀の匏で構成される方法も瀺しおいたす。

むテレヌタ


退屈なカりントの䟋に戻りたしょう。

 echo("  : ") for i in countup(1, 10): echo($i) 

countupそのようなサむクルで䜿甚する手順を曞くこずは可胜ですか詊しおみたしょう

 proc countup(a, b: int): int = var res = a while res <= b: return res inc(res) 

残念ながら、これは機胜したせん。問題は、プロシヌゞャが倀を返すだけでなく、次の反埩で戻っお䜜業を続行する必芁があるこずです。この「戻り、続行」はチヌムず呌ばれyieldたす。これで、キヌワヌドを眮き換えるだけprocでiterator、ここにありたす-最初のむテレヌタヌ

 iterator countup(a, b: int): int = var res = a while res <= b: yield res inc(res) 

むテレヌタは手順に非垞に䌌おいたすが、いく぀かの重芁な違いがありたす。

ただし、closure異なる制限のセットを持぀むテレヌタヌを䜿甚するこずもできたす。詳现に぀いおは、「ファヌストクラスむテレヌタ」のドキュメントセクションを参照しおください。むテレヌタは、プロシヌゞャず同じ名前ずパラメヌタを持぀こずができたす。独自の名前空間を持ちたす。したがっお、むテレヌタの結果を蓄積splitし、moduleからのようにシヌケンスの圢匏で返す同じ名前のプロシヌゞャでむテレヌタをラップする䞀般的な方法がありたすstrutils。

基本タむプ


このセクションでは、基本的な組み蟌みタむプずそれらで䜿甚可胜な操䜜に぀いお詳しく説明したす。

ブヌル倀


Nimの論理型が呌び出さboolれ、2぀の定矩枈みの倀、trueおよびで構成されたすfalse。コマンドでの条件はwhile、if、elifおよびwhenタむプを持っおいる必芁がありたすbool。

タむプのためにbool定矩された事業者not、and、or、xor、<、<=、>、>=、!=ず==。挔算子andずor短瞮蚈算を実行したす。䟋

 while p != nil and p.name != "xyz": # p.name  ,  p == nil p = p.next 

キャラクタヌ


Nim の文字タむプはず呌ばれcharたす。サむズは1バむトです。したがっお、UTF-8文字にするこずはできたせん。その䞀郚のみです。この理由は効率性です。UTF-8はこのために特別に開発されおいるため、ほずんどの堎合、完成したプログラムはUTF-8でデヌタを正しく凊理したす。文字リテラルは単䞀匕甚笊で囲たれたす。

蚘号は、挔算子を䜿甚しお比范するこずができ==、<、<=、>ずしたす>=。挔算子はに$倉換さcharれstringたす。文字を敎数ず混圚させるこずはできたせん。手順を䜿甚しお、文字の数倀を取埗したすord。数倀から文字ぞの倉換は、プロシヌゞャを䜿甚しお実行されたすchr。

行


Nimの文字列倀は可倉なので、郚分文字列を文字列に远加する操䜜は非垞に効率的です。 Nimの行は同時にれロで終わり、長さフィヌルドを含みたす。文字列の長さは、組み蟌みプロシヌゞャによっお取埗できたすlen。長さは、終端のれロを考慮に入れたせん。末尟のれロにアクセスしおも゚ラヌは発生せず、倚くの堎合、コヌドが簡玠化されたす。

 if s[i] == 'a' and s[i+1] == 'b': #   ,  i < len(s)! ... 

文字列の代入挔算子は、文字列をコピヌしたす。挔算子&を䜿甚しお、ストリングを連結しadd、サブストリングを远加できたす。

文字列の比范は蟞曞匏順序で行われたす。すべおの比范挔算子が蚱可されたす。慣䟋により、すべおの行はUTF-8行ですが、これは必須ではありたせん。たずえば、バむナリファむルから文字列を読み取る堎合、文字列はバむトシヌケンスである可胜性が高くなりたす。操䜜s[i]ずは、文字列のii番目の文字in番目のUnicode文字ではないを意味したすs。

文字列倉数はず呌ばれる特別な倀で初期化されnilたす。ただし、ほずんどの文字列操䜜はnilこれにより、䟋倖が発生したすパフォヌマンス䞊の理由から。代わりにnil、空の文字列を空の倀ずしお䜿甚したす""。ただし""、ヒヌプ䞊に文字列オブゞェクトが䜜成されるため、ここではメモリずパフォヌマンスの劥協点を芋぀ける必芁がありたす。

敎数


ニムは、組み蟌みの敎数型の次がありたすint、int8、int16、int32、int64、uint、uint8、uint16、uint32ずuint64。

デフォルトは敎数型intです。敎数リテラルには、1぀たたは別の敎数型に属するこずを瀺す接尟蟞を付けるこずができたす。

 let x = 0 # x   int y = 0'i8 # y   int8 z = 0'i64 # z   int64 u = 0'u # u   uint 

ほずんどの堎合、敎数はメモリに栌玍されおいるオブゞェクトをカりントするために䜿甚されるため、サむズintはポむンタヌのサむズず等しくなりたす。

倧手事業者+、-、*、div、mod、<、<=、==、!=、>および>=敎数のために定矩されたした。挔算子and、or、xorおよびnot敎数に察しお定矩され、ビット挔算を実行するように。巊ビットシフトは挔算子を䜿甚しお行われshl、右シフトは挔算子を䜿甚しお行われshrたす。ビットシフト挔算子は、垞に匕数を笊号なしの数倀ずしお扱いたす。乗算たたは陀算に䜿甚できたす。

すべおの眲名されおいない操䜜にはラッパヌが装備されおいるため、オヌバヌフロヌ゚ラヌが発生するこずはありたせん。

自動型倉換は、異なる敎数型を䜿甚する匏で実行されたす。ただし、型倉換によっお情報が倱われるず、䟋倖が発生したすEOutOfRangeコンパむル段階で゚ラヌが怜出されなかった堎合。

浮動小数点数


ニムは内蔵の浮動小数点数の皮類以䞋がありたすfloat、float32ずfloat64。

デフォルトでは、タむプが䜿甚されfloatたす。珟圚の実装でfloatは、サむズは垞に64ビットです。

浮動小数点リテラルには、1぀たたは別のタむプの浮動小数点数に属するこずを瀺す接尟蟞を付けるこずができたす。

 var x = 0.0 # x   float y = 0.0'f32 # y   float32 z = 0.0'f64 # z   float64 

䞻芁オペレヌタヌ+、-、*、/、<、<=、==、!=、>および>=IEEE芏栌にポむント番号ず察応しおフロヌティングために定矩されたした。

さたざたなタむプの浮動小数点型を持぀匏の自動型倉換が実行されたす。小さな型は倧きな型に倉換されたす。敎数型は浮動小数点型に自動的に倉換されず、その逆も行われたせん。このような倉換には、toIntおよびプロシヌゞャを䜿甚できたすtoFloat。

型倉換


Nimのベヌスタむプ間の倉換は、タむプを関数ずしお䜿甚するこずで実珟されたす。

 var x: int32 = 1.int32 #  ,   int32(1) y: int8 = int8('a') # 'a' == 97'i8 z: float = 2.5 # int(2.5)   2 sum: int = int(x) + int(y) + int(z) # sum == 100 

型の内郚衚珟


前述したように、文字列ぞの組み蟌みの倉換挔算子は、$任意の基本型を、プロシヌゞャを䜿甚しお衚瀺できる文字列に倉換したすecho。ただし、オペレヌタヌ$は、耇雑なタむプたたは自分で䜜成したタむプを、再定矩するたで操䜜できたせん。

時々、デバッグ時に、別の挔算子を蚘述するこずなく、耇合型の倀を芋぀けるこずが必芁になりたす$。この堎合、repr任意のタむプ、さらには耇雑な埪環デヌタグラフでも機胜する手順を䜿甚できたす。次の䟋は、基本タむプであっおも、結果$ずの間に違いがあるこずを瀺しおいたすrepr。

 var myBool = true myCharacter = 'n' myString = "nim" myInteger = 42 myFloat = 3.14 echo($myBool, ":", repr(myBool)) # --> true:true echo($myCharacter, ":", repr(myCharacter)) # --> n:'n' echo($myString, ":", repr(myString)) # --> nim:0x10fa8c050"nim" echo($myInteger, ":", repr(myInteger)) # --> 42:42 echo($myFloat, ":", repr(myFloat)) # --> 3.1400000000000001e+00:3.1400000000000001e+00 

远加の皮類


Nimの新しいタむプは、次のコマンドを䜿甚しお定矩できたすtype。

 type biggestInt = int64 #  , ,    biggestFloat = float64 #    , ,    

列挙ずオブゞェクトタむプは、コマンドでのみ「オンザフラむ」で定矩できたせんtype。

乗り換え


列挙のタむプに関連する倉数は、限られた倀のセットのみを取るこずができたす。このセットは、順序付けられた文字で構成されおいたす。各文字は内郚的に敎数倀にマップされたす。最初の文字は数字の0に察応し、2番目の文字は数字の1に察応したす。䟋

 type Direction = enum north, east, south, west var x = south # `x`   `Direction`;   `south` echo($x) #  "south"  `stdout` 

転送には、任意の比范挔算子を䜿甚できたす。

シンボルを転送するのを回避するために分類できたすDirection.south。

挔算子$は、列挙の倀を自分の名前に倉換し、プロシヌゞャordを察応する敎数倀に倉換できたす。

他のプログラミング蚀語ずのより良い察話のために、列挙文字に敎数倀を明瀺的に割り圓おるこずができたす。ただし、いずれにしおも、昇順でなければなりたせん。明瀺的に数倀が割り圓おられおいない文字は、前の文字に1を加えた倀を受け取りたす。

明瀺的に番号付けされた列挙には、省略が含たれる堎合がありたす。

 type MyEnum = enum a = 2, b = 4, c = 89 

列挙型


䌑憩なしで転送し、敎数型char、boolおよびそのサブバンド -圌らは列挙型ず呌ばれおいたす。列挙型には、いく぀かの特別な操䜜がありたす。
運営解説
ord(x)倀を衚すために䜿甚される敎数を返したす x
inc(x)x1 ず぀増加
inc(x, n)増加xにn; n敎数です
dec(x)x1 枛少
dec(x, n)によっお枛少xしnたす。n敎数です
succ(x)次のxアむテムを返したす
succ(x, n)n次の芁玠を返したすx
pred(x)先行を返したす x
pred(x, n)n先行を返したすx

操䜜はinc、dec、succおよびpred゚ラヌで実行するこずができ、䟋倖がスロヌされたすEOutOfRangeかEOverflow。もちろん、䟋倖チェックを有効にしおコヌドをコンパむルしない限り。

範囲


この型は、敎数型たたは列挙型基本型の倀の範囲です。 䟋

 type Subrange = range[0..5] 

Subrangeこれは、int0〜5の倀を含むこずができる範囲です。他の倀を型倉数に割り圓おるSubrangeず、コンパむル゚ラヌたたは実行時゚ラヌが発生したす。基本タむプをその範囲の1぀におよびその逆に割り圓おるこずは蚱可されおいたす。

モゞュヌルsystemは、重芁なタむプNaturalをrange[0..high(int)]high蚱可される最倧倀を返したすずしお定矩したす。他のプログラミング蚀語では、自然数を扱うために笊号なし敎数を䜿甚する必芁がありたす。これはしばしば間違っおいたす。数字を負にできないずいう理由だけで、笊号なし算術の䜿甚を匷制されるべきではありたせん。NaturalNim蚀語タむプは、この䞀般的なプログラミング゚ラヌを回避したす。

倚くの


タむプsetは、セットの数孊的抂念をモデル化したす。セットの基本型は、特定のサむズの列挙型のみです。぀たり、たたは同等。その理由は、セットが高性胜ビットベクトルずしお実装されおいるためです。より倧きなセットを宣蚀しようずするず、゚ラヌが発生したす。

 var s: set[int64] # Error: set is too large 

セットは、セットコンストラクタヌを䜿甚しお構築できたす。{}これは空のセットです。空のセットは、特定のタむプのセットずタむプ互換性がありたす。コンストラクタヌを䜿甚しお、芁玠および芁玠の範囲を含めるこずもできたす。

 type CharSet = set[char] var x: CharSet x = {'a'..'z', '0'..'9'} #   ,    # 'a'  'z'    '0'  '9' 

セットでは、次の操䜜がサポヌトされおいたす。
運営説明
A + B2぀のセットの結合
A * B2぀のセットの亀差点
A - B2぀のセットの差A芁玠なしB
A == Bセットの平等
A <= Bサブセット関係AサブセットBたたは同等物B
A < B厳密なサブセット関係AサブセットですB
e in AセットのメンバヌシップA芁玠を含むe
e notin AA 芁玠を含たない e
contains(A, e)A 芁玠を含む e
card(A)パワヌAの芁玠数A
incl(A, elem)ず同じ A = A + {elem}
excl(A, elem)ず同じ A = A - {elem}

倚くの堎合、手順フラグにスコアが䜿甚されたす。これは、操䜜で結合する必芁がある敎数定数を定矩するよりも透明性の高いタむプセヌフな゜リュヌションですor。

配列


配列は、固定サむズの単玔なコンテナです。すべおの芁玠は同じ型です。任意の列挙型を配列むンデックスずしお䜿甚できたす。

配列は次を䜿甚しお䜜成できたす[]。

 type IntArray = array[0..5, int] #   ,   0  5 var x: IntArray x = [1, 2, 3, 4, 5, 6] for i in low(x)..high(x): echo(x[i]) 

衚蚘はx[i]、ii番目の芁玠にアクセスするために䜿甚されたすx。配列芁玠にアクセスする堎合、コンパむル時たたは実行時に垞に境界がチェックされたす。このチェックは、プラグマによっお、たたはキヌを䜿甚しおコンパむラを呌び出すこずによっお無効にできたす--bound_checks:off。

配列は、他のNim型ず同様に倀型です。代入挔算子は、配列の内容党䜓をコピヌしたす。

組み蟌みプロシヌゞャlenは、配列の長さを返したす。low(a)配列の可胜な最小のむンデックスaず、high(a)可胜な最倧のむンデックスを返したす。

 type Direction = enum north, east, south, west BlinkLights = enum off, on, slowBlink, mediumBlink, fastBlink LevelSetting = array[north..west, BlinkLights] var level: LevelSetting level[north] = on level[south] = slowBlink level[east] = fastBlink echo repr(level) # --> [on, fastBlink, slowBlink, off] echo low(level) # --> north echo len(level) # --> 4 echo high(level) # --> west 

通垞、各次元は他の次元ず同じ型である必芁があるため、他の蚀語のネストされた配列耇数の次元の構文は、角括匧を远加するこずになりたす。 Nimでは、異なるむンデックスタむプで異なるディメンションを䜿甚できるため、ネスト構文はわずかに異なりたす。level別の列挙によっおむンデックスが付けられた列挙の配列ずしお定矩されおいる前の䟋に基づいお、次の行を远加しお、ビヌコンのタむプを敎数むンデックスからアクセスできるレベルに分割できるようにしたす。

 type LightTower = array[1..10, LevelSetting] var tower: LightTower tower[1][north] = slowBlink tower[1][east] = mediumBlink echo len(tower) # --> 10 echo len(tower[1]) # --> 4 echo repr(tower) # --> [[slowBlink, mediumBlink, ... .... #     -   #tower[north][east] = on #tower[0][1] = on 

組み蟌みプロシヌゞャlenは、最初のレベルの配列の長さのみを返すこずに泚意しおください。ネストされた性質をよりよく瀺すLightTowerために、前の型定矩を蚘述できたせんでしたLevelSettingが、代わりに最初の次元の型に盎接含めるこずができたした。

 type LightTower = array[1..10, array[north..west, BlinkLights]] 

倚くの堎合、配列はれロから始たりたす。そのため、範囲を0から指定されたむンデックスから1を匕いた倀に蚭定するための簡単な構文がありたす。

 type IntArray = array[0..5, int] # ,   0  5 QuickArray = array[6, int] # ,   0  5 var x: IntArray y: QuickArray x = [1, 2, 3, 4, 5, 6] y = x for i in low(x)..high(x): echo(x[i], y[i]) 

シヌケンス


シヌケンスは配列に䌌おいたすが、実行時に倉曎できるのは長さだけです文字列ず同様。シヌケンスはサむズを倉曎できるため、垞にヒヌプに配眮され、ガベヌゞコレクションに関䞎したす。

シヌケンスは垞にむンデックスさint0の操䜜で始たりlen、lowおよびhighシヌケンスのために䟿利です。衚蚘x[i]を䜿甚しお、ii番目の芁玠にアクセスできたすx。

配列は[]、配列から配列ぞの挔算子に接続された配列コンストラクタヌを䜿甚しお構築できたす@。シヌケンスにメモリを割り圓おるもう1぀の方法は、組み蟌みプロシヌゞャを呌び出すこずnewSeqです。

シヌケンスはパラメヌタで枡すこずができたすopenarray。

䟋

 var x: seq[int] #      x = @[1, 2, 3, 4, 5, 6] # @    ,    

シヌケンス倉数は倀で初期化されたすnil。ただし、シヌケンス䞊のほずんどの操䜜はnil、パフォヌマンス䞊の理由で機胜したせんこれにより䟋倖がスロヌされたす。それで、空倀ずしお空のシヌケンスを䜿甚するのは賢明であるより賢明@[]ですnil。ただし@[]、ヒヌプ䞊にシヌケンスオブゞェクトが䜜成されるため、特定のケヌスに適した゜リュヌションを探す必芁がありたす。シヌケンスに䜿甚される

コマンドforは、1぀たたは2぀の倉数で機胜したす。 1぀の倉数を持぀フォヌムを䜿甚する堎合、倉数にはシヌケンスによっお提䟛される倀が含たれたす。チヌムforは、items()モゞュヌル反埩子から埗られた結果に埓いたすsystem。ただし、2぀の倉数を持぀フォヌムを䜿甚する堎合、最初の倉数には䜍眮むンデックスが含たれ、2番目の倉数には倀が含たれたす。この堎合、コマンドはmoduleのfor反埩子の結果に埓いpairs()たすsystem。䟋

 for i in @[3, 4, 5]: echo($i) # --> 3 # --> 4 # --> 5 for i, value in @[3, 4, 5]: echo("index: ", $i, ", value:", $value) # --> index: 0, value:3 # --> index: 1, value:4 # --> index: 2, value:5 

オヌプンアレむ


泚オヌプン配列は、パラメヌタヌずしおのみ䜿甚できたす。
倚くの堎合、固定サむズの配列は十分な柔軟性を持たないこずが刀明しおいたす。プロシヌゞャは、異なるサむズの配列を凊理する必芁がある堎合がありたす。これにはオヌプンアレむタむプがありたす。オヌプン配列は垞に敎数でむンデックス化されおおり、ナンバリングは圌らのために0で䜿甚可胜な操䜜を開始しlen、lowそしおhigh。互換性のあるベヌス型を持぀配列は、オヌプン配列パラメヌタヌずしお枡すこずができたす;むンデックス型は関係ありたせん。

 var fruits: seq[string] #    ,  #   'nil' capitals: array[3, string] #      fruits = @[] #     ,  #    'fruits' capitals = ["New York", "London", "Berlin"] #  'capitals'  #     fruits.add("Banana") #  'fruits'  #     fruits.add("Mango") proc openArraySize(oa: openArray[string]): int = oa.len assert openArraySize(fruits) == 2 #    #    assert openArraySize(capitals) == 3 #     

オヌプン配列のタむプをネストするこずはできたせん。倚次元オヌプン配列の必芁性はめったに発生せず、効率的に実装できないため、倚次元オヌプン配列はサポヌトされおいたせん。

任意の数の匕数を持぀パラメヌタヌ


パラメヌタヌvarargsは、開いおいる配列に䌌おいたす。ただし、さらに、任意の数の匕数をプロシヌゞャに枡すこずができたす。コンパむラヌは、匕数リストを自動的に配列に倉換したす。

 proc myWriteln(f: File, a: varargs[string]) = for s in items(a): write(f, s) write(f, "\n") myWriteln(stdout, "abc", "def", "xyz") #   : myWriteln(stdout, ["abc", "def", "xyz"]) 

この倉換は、パラメヌタヌがvarargsプロシヌゞャのヘッダヌの最埌の堎合にのみ行われたす。このコンテキストで型倉換を実行するこずもできたす。

 proc myWriteln(f: File, a: varargs[string, `$`]) = for s in items(a): write(f, s) write(f, "\n") myWriteln(stdout, 123, "abc", 4.0) #   : myWriteln(stdout, [$123, $"abc", $4.0]) 

この䟋$は、パラメヌタヌを介しお枡されるすべおの匕数に適甚されたすa。$文字列に適甚しおも䜕も行われないこずに泚意しおください。

スラむス数


構文スラむスは範囲タむプに䌌おいたすが、異なるコンテキストで䜿甚されたす。スラむス-それはタむプの単なるオブゞェクトのSlice2぀の境界が含たれ、aそしおb。スラむス自䜓はあたり有甚ではありたせんが、他のタむプのコレクションはSlice、範囲を蚭定するオブゞェクトを受け入れる挔算子によっお定矩されたす。

  var a = "Nim is a progamming language" b = "Slices are useless." echo a[7..12] # --> 'a prog' b[11..^2] = "useful" echo b # --> 'Slices are useful.' 

前の䟋では、文字列のフラグメントを倉曎するためにスラむスが䜿甚されおいたす。スラむスの境界には、そのタむプでサポヌトされおいる任意の倀を含めるこずができたすが、この倀を受け入れるかどうかは、スラむスオブゞェクトを䜿甚するプロシヌゞャのみが決定したす。

タプル


タプルのタむプは、異なる名前のフィヌルドずこれらのフィヌルドの順序を定矩したす。タプルを構築するには、コンストラクタヌを䜿甚できたす()。コンストラクタヌのフィヌルド順序は、タプル定矩のフィヌルド順序ず䞀臎する必芁がありたす。異なるタむプのタプルは、同じ名前の同じタむプのフィヌルドを同じ順序で指定する堎合、同等ず芋なされたす。

タプルの割り圓お挔算子は、各コンポヌネントをコピヌしたす。t.fieldタプルフィヌルドぞのアクセスには衚蚘法が䜿甚されたす。別の衚蚘法t[i]は、i-thフィヌルドぞのアクセスを提䟛したすi敎数定数でなければなりたせん。

 type Person = tuple[name: string, age: int] #   ,  #      var person: Person person = (name: "Peter", age: 30) #  ,   : person = ("Peter", 30) echo(person.name) # "Peter" echo(person.age) # 30 echo(person[0]) # "Peter" echo(person[1]) # 30 #         . var building: tuple[street: string, number: int] building = ("Rue del Percebe", 13) echo(building.street) #    ,   ! #person = building # --> Error: type mismatch: got (tuple[street: string, number: int]) # but expected 'Person' #   ,       . var teacher: tuple[name: string, age: int] = ("Mark", 42) person = teacher 

タプルを䜿甚するために型を宣蚀する必芁はありたせんが、異なるフィヌルド名で䜜成されたタプルは、同じフィヌルド型を持぀堎合でも、異なるオブゞェクトず芋なされたす。

タプルは、倉数を割り圓おるプロセスでアンパックできたすこの堎合のみ。これは、タプルフィヌルド倀を個々の名前付き倉数に盎接割り圓おるのに䟿利です。䟋ずしお、ディレクトリ、名前、およびパス拡匵子の䞡方を返すsplitFileモゞュヌルのプロシヌゞャを考えosたす。タプルを適切にアンパックするには、タプルをアンパックする倀をカッコで囲む必芁がありたす。そうでない堎合は、これらの各倉数に同じ倀を割り圓おたす䟋

 import os let path = "usr/local/nimc.html" (dir, name, ext) = splitFile(path) baddir, badname, badext = splitFile(path) echo dir #  usr/local echo name #  nimc echo ext #  .html #        : # `(dir: usr/local, name: nimc, ext: .html)` echo baddir echo badname echo badext 

タプルのアンパックは、ブロックvarたたはでのみ機胜したすlet。次のコヌドはコンパむルされたせん。

 import os var path = "usr/local/nimc.html" dir, name, ext = "" (dir, name, ext) = splitFile(path) # --> Error: '(dir, name, ext)' cannot be assigned to 

参照タむプずポむンタヌ


参照他のプログラミング蚀語のポむンタヌず同じは、倚察1の関係を敎理する方法です。これは、異なるリンクがメモリ内の同じ堎所を指し、倉曎できるこずを意味したす。

Nimは、トレヌスされたリンクずトレヌスされおいないリンクを区別したす。远跡されおいないリンクは、ポむンタヌずも呌ばれたす。远跡されたリンクは、ガベヌゞコレクションでヒヌプ䞊のオブゞェクトを指し、远跡されおいないリンクは、メモリが手動で割り圓おられたオブゞェクトたたは他のメモリ䜍眮のオブゞェクトを指したす。したがっお、远跡されおいないリンクは安党ではありたせん。ただし、䞀郚の䜎レベル操䜜ハヌドりェアぞのアクセスに぀いおは、それらなしでは実行できたせん。

远跡されたリンクは、キヌワヌドによっお宣蚀され、远跡されたせんref-キヌワヌドによっおptr。

空の添字衚蚘[]を䜿甚しお、リンクの逆参照、぀たりリンクが指す芁玠を取埗できたす。挔算子.タプル/オブゞェクトフィヌルドぞのアクセスおよび[]配列/行/シヌケンスむンデックス挔算子は、参照型の暗黙的な逆参照を実行したす。

 type Node = ref NodeObj NodeObj = object le, ri: Node data: int var n: Node new(n) n.data = 9 #    n[].data,     ! 

組み蟌みプロシヌゞャを䜿甚しお、新しい監芖察象オブゞェクトにメモリを割り圓おたすnew。䜜業手順に远跡䞍可胜なメモリを䜿甚するこずができalloc、deallocそしおrealloc。モゞュヌルのドキュメントにsystemは、これらの問題に関する远加情報が含たれおいたす。

リンクが䜕かを指しおいない堎合、それは重芁nilです。

手続き型


手続き型は、手続きぞのやや抜象的なポむンタです。手続き型倉数はvalueを取るこずができたすnil。Nimは手続き型を䜿甚しお関数型プログラミング手法を実装したす。

䟋

 proc echoItem(x: int) = echo(x) proc forEach(action: proc (x: int)) = const data = [2, 3, 5, 7, 11] for d in items(data): action(d) forEach(echoItem) 

手続き型の非自明な問題は、手続き呌び出し芏則が型の互換性に圱響するこずです。手続き型は、同じ呌び出し芏則を䜿甚する堎合にのみ互換性がありたす。さたざたな呌び出し芏玄がマニュアルに蚘茉されおいたす。

モゞュヌル


Nimは、モゞュヌル性の抂念に埓っおプログラムを分割するこずをサポヌトしおいたす。各モゞュヌルは個別のファむルにありたす。モゞュヌルを䜿甚するず、情報の非衚瀺ず個別のコンパむルを実行できたす。コマンドを䜿甚しお、他のモゞュヌルのシンボルにアクセスできたすimport。゚クスポヌトできるのは、アスタリスク*でマヌクされた最䞊䜍のシンボルのみです。

 #  A var x*, y: int proc `*` *(a, b: seq[int]): seq[int] = #   : newSeq(result, len(a)) #    : for i in 0..len(a)-1: result[i] = a[i] * b[i] when isMainModule: #    ``*``  : assert(@[1, 2, 3] * @[1, 2, 3] == @[1, 4, 9]) 


モゞュヌルはをA゚クスポヌトxしたす*が、ではありたせんy。

モゞュヌルのトップレベルのコマンドは、プログラムの起動時に実行されたす。これは、たずえば、耇雑なデヌタ構造を初期化するために䜿甚できたす。

各モゞュヌルには特別なマゞック定数isMainModuleがありたす。これは、モゞュヌルがメむンファむルずしおコンパむルされる堎合に圓おはたりたす。これは、前の䟋で瀺したように、テストモゞュヌルを内郚に埋め蟌むのに非垞に䟿利です。

他のモゞュヌルに䟝存するモゞュヌルは蚱可されたすが、非垞に望たしくありたせん。この堎合、モゞュヌルは䟝存関係なしでは再利甚できないためです。

モゞュヌルのコンパむルアルゎリズムは次のずおりです。


これは、䟋で最もよく瀺されたす。

 #  A type T1* = int #  A   ``T1`` import B #    B proc main() = var i = p(3) # ,  B     main() 

 #  B import A # A      !     # ,    A   . proc p*(x: A.T1): A.T1 = #  ,     T1    A result = x + 1 

モゞュヌル文字は、構文を䜿甚しお修食できたすmodule.symbol。シンボルがあいたいな堎合、修食する必芁がありたす。シンボルが2぀たたはそれ以䞊の異なるモゞュヌルで定矩され、䞡方のモゞュヌルが3番目のモゞュヌルによっおむンポヌトされる堎合、シンボルはあいたいです。

 #  A var x*: string 

 #  B var x*: int 

 #  C import A, B write(stdout, x) # : x  write(stdout, Ax) #  :   var x = 4 write(stdout, x) #  :  x  C 

ただし、この芏則はプロシヌゞャたたはむテレヌタには適甚されたせん。オヌバヌロヌドルヌルはここに適甚されたす。

 #  A proc x*(a: int): string = $a 

 #  B proc x*(a: string): string = $a 

 #  C import A, B write(stdout, x(3)) #  :  Ax write(stdout, x("")) #  :  Bx proc x*(a: int): string = nil write(stdout, x(3)) # :  `x` ? 

キャラクタヌの陀倖


通垞、コマンドimportぱクスポヌトされたすべおの文字を受け取りたす。これは、修食子で陀倖文字を指定するこずで倉曎できたすexcept。

 import mymodule except y 

コマンドから


import゚クスポヌトされたすべおの文字をむンポヌトする簡単なコマンドを芋おきたした。次のコマンドを䜿甚するず、リストされおいる文字のみをむンポヌトできたすfrom import。

 from mymodule import x, y, z 

コマンドfromは、䜿甚可胜な文字の結果ずしお、文字のネヌムスペヌスを匷制するこずもできたすが、それらを䜿甚するには、修食子を指定する必芁がありたす。

 from mymodule import x, y, z x() #  x   

 from mymodule import nil mymodule.x() #   x,       x() #  x       

モゞュヌル名は通垞非垞に長いため、修食で䜿甚される短い゚むリアスを指定するこずもできたす。

 from mymodule as m import nil mx() # m    mymodule 

コマンドを含める


チヌムincludeは、モゞュヌルのむンポヌトずは根本的に異なるこずを行いたす。ファむルの内容をその堎所に挿入したす。このコマンドは、倧きなモゞュヌルをいく぀かのファむルに分割するのに非垞に䟿利です。

 include fileA, fileB, fileC 


続きを远加「Nimチュヌトリアルパヌト2。」

Source: https://habr.com/ru/post/J271197/


All Articles