Nim (ранее известный, как Nimrod) — язык программирования со статической типизацией, поддерживающий процедурный, объектно-ориентированный, функциональный и обобщённый стили программирования.
Nim эффективный, выразительный и элегантный.
1var # Объявление (и присваивание) переменных,
2 буква: char = 'n' # с указанием типа или без
3 язык = "N" & "im"
4 nLength : int = len(язык)
5 boat: float
6 правда: bool = false
7
8let # Используйте let *сразу* для объявления и связывания переменных.
9 ноги = 400 # ноги неизменяемый.
10 руки = 2_000 # Символ _ игнорируется и удобен для длинных чисел.
11 почтиПи = 3.15
12
13const # Константы вычисляются во время компиляции. Это обеспечивает
14 debug = true # производительность и полезно в выражениях этапа компиляции.
15 компилироватьПлохойКод = false
16
17when компилироватьПлохойКод: # `when` это `if` этапа компиляции.
18 ноги = ноги + 1 # Эта ошибка никогда не будет скомпилирована.
19 const ввод = readline(stdin) # Значения констант должны быть известны во
20 # время компиляции.
21
22discard 1 > 2 # Примечание. Компилятор будет жаловаться, если результат
23 # выражения не используется. `discard` обходит это.
24
25discard """
26Это может использоваться как многострочный комментарий.
27Или для не поддающегося синтаксическому анализу, сломанного кода
28"""
29
30#
31# Структуры данных
32#
33
34# Кортежи
35
36var
37 дитя: tuple[имя: string, возраст: int] # Кортежи определяют *как* имя поля
38 сегодня: tuple[солнце: string, температура: float] # так *и* порядок полей.
39
40дитя = (имя: "Rudiger", возраст: 2) # Присвоить все сразу литералом ()
41сегодня.солнце = "Пасмурно" # или отдельно по полям.
42сегодня.температура = 20.1
43
44# Последовательности
45
46var
47 напитки: seq[string]
48
49напитки = @["Вода", "Сок", "Какао"] # @[V1,..,Vn] является литералом
50 # последовательности
51
52напитки.add("Молоко")
53
54if "Молоко" in напитки:
55 echo "У нас тут Молоко и ещё", напитки.len - 1, " напиток(ов)"
56
57let мойНапиток = напитки[2]
58
59#
60# Определение типов
61#
62
63# Определение собственных типов позволяет компилятору работать на вас.
64# Это то, что делает статическую типизацию мощной и полезной.
65
66type
67 Имя = string # Псевдоним типа дает вам новый тип, который равнозначен
68 Возраст = int # старому типу, но более нагляден.
69 Человек = tuple[имя: Имя, возраст: Возраст] # Определение структур данных.
70 АльтернативныйСинтаксис = tuple
71 fieldOne: string
72 secondField: int
73
74var
75 джон: Человек = (имя: "John B.", возраст: 17)
76 новыйВозраст: int = 18 # Было бы лучше использовать Возраст, чем int
77
78джон.возраст = новыйВозраст # Но это все же работает, потому что int и Возраст синонимы.
79
80type
81 Нал = distinct int # `distinct` делает новый тип несовместимым с его
82 Описание = distinct string # базовым типом.
83
84var
85 money: Нал = 100.Нал # `.Нал` преобразует int в наш тип
86 описание: Описание = "Interesting".Описание
87
88when компилироватьПлохойКод:
89 джон.возраст = money # Error! возраст is of type int and money is Нал
90 джон.имя = описание # Компилятор говорит: "Нельзя!"
91
92#
93# Дополнительные типы и структуры данных
94#
95
96# Перечисления позволяют типу иметь одно из ограниченного числа значений
97
98type
99 Цвет = enum цКрасный, цГолубой, цЗеленый
100 Направление = enum # Альтернативный формат
101 нСевер
102 нЗапад
103 нВосток
104 нЮг
105var
106 напр = нСевер # `напр` имеет тип Направление, со значением `нСевер`
107 точка = цЗеленый # `точка` имеет тип Цвет, со значением `цЗеленый`
108
109discard нСевер > нВосток # Перечисления обычно являются "порядковыми" типами
110
111# Поддиапазоны определяют ограниченный допустимый диапазон
112
113type
114 Кости = range[1..20] # 🎲 Допустимым значением являются только int от 1 до 20
115var
116 мой_бросок: Кости = 13
117
118when компилироватьПлохойКод:
119 мой_бросок = 23 # Error!
120
121# Массивы
122
123type
124 СчетчикБросков = array[Кости, int] # Массивы фиксированной длины и
125 ИменаНаправлений = array[Направление, string] # индексируются любым порядковым типом.
126 Истины = array[42..44, bool]
127var
128 счетчик: СчетчикБросков
129 направления: ИменаНаправлений
130 возможны: Истины
131
132возможны = [false, false, false] # Массивы создаются литералом [V1,..,Vn]
133возможны[42] = true
134
135направления[нСевер] = "ОО. Великий белый Север!"
136направления[нЗапад] = "Нет, не иди туда."
137
138мой_бросок = 13
139счетчик[мой_бросок] += 1
140счетчик[мой_бросок] += 1
141
142var ещеМассив = ["Идекс по умолчанию", "начинается с", "0"]
143
144# Доступны другие структуры данных, в том числе таблицы, множества,
145# списки, очереди и crit-bit деревья.
146# http://nim-lang.org/docs/lib.html#collections-and-algorithms (EN)
147
148#
149# IO и поток управления выполнением
150#
151
152# `case`, `readLine()`
153
154echo "Читали какие-нибудь хорошие книги в последнее время?"
155
156case readLine(stdin)
157of "нет", "Нет":
158 echo "Пойдите в свою местную библиотеку."
159of "да", "Да":
160 echo "Тогда продолжим"
161else:
162 echo "Здорово!"
163
164# `while`, `if`, `continue`, `break`
165
166import strutils as str # http://nim-lang.org/docs/strutils.html (EN)
167echo "Я загадало число между 41 и 43. Отгадай!"
168let число: int = 42
169var
170 ввод_догадка: string
171 догадка: int
172
173while догадка != число:
174 ввод_догадка = readLine(stdin)
175
176 if ввод_догадка == "": continue # Пропустить эту итерацию
177
178 догадка = str.parseInt(ввод_догадка)
179
180 if догадка == 1001:
181 echo("AAAAAAGGG!")
182 break
183 elif догадка > число:
184 echo("Неа. Слишком большое.")
185 elif догадка < число:
186 echo(догадка, " это слишком мало")
187 else:
188 echo("Точнооооо!")
189
190#
191# Итерации (циклы)
192#
193
194for i, элем in ["Да", "Нет", "Может быть"]: # Или просто `for элем in`
195 echo(элем, " по индексу: ", i)
196
197for ключ, значение in items(@[(человек: "You", сила: 100), (человек: "Me", сила: 9000)]):
198 echo значение
199
200let мояСтрока = """
201<пример>
202`строки` для
203тренировки
204""" # Многострочная "сырая" строка
205
206for строка in splitLines(мояСтрока):
207 echo(строка)
208
209for i, симв in мояСтрока: # Индекс и символ. Или `for j in` только для символов
210 if i mod 2 == 0: continue # Компактная форма `if`
211 elif симв == 'X': break
212 else: echo(симв)
213
214#
215# Процедуры
216#
217
218type Ответ = enum оДа, оНет
219
220proc спрос(вопрос: string): Ответ =
221 echo(вопрос, " (д/н)")
222 while true:
223 case readLine(stdin)
224 of "д", "Д", "да", "Да":
225 return Ответ.оДа # Перечисления могут быть квалифицированы
226 of "н", "Н", "нет", "Нет":
227 return Ответ.оНет
228 else: echo("Поточнее, да или нет")
229
230proc добавьСахар(количество: int = 2) = # Значение по умолчанию 2, ничего не возвращает
231 assert(количество > 0 and количество < 9000, "Диабет ☠")
232 for a in 1..количество:
233 echo(a, " кубик...")
234
235case спрос("Сахарку?")
236of оДа:
237 добавьСахар(3)
238of оНет:
239 echo "Ну немнооожко!"
240 добавьСахар()
241# Здесь нет необходимости в `else`. Возможны только `да` и `нет`.
242
243#
244# FFI (интерфейс внешних функций)
245#
246
247# Так как Nim компилируется в C, то FFI делается очень просто:
248
249proc strcmp(a, b: cstring): cint {.importc: "strcmp", nodecl.}
250
251let cmp = strcmp("C?", "Легко!")
Кроме того, Nim выделяется среди себе подобных метапрограммированием, производительностью, функциями этапа компиляции.