高效、优雅、富有表现力

Nim 是一种静态类型的、编译型、系统编程语言。
它结合了其他成熟语言的成功概念。
(如 Python、Ada 和 Modula)

效率

  • Nim 生成原生且无依赖的可执行文件,不依赖于虚拟机,
    所以它们小巧易分发。
  • Nim 编译器和生成的可执行文件,对目前的任何主流平台都提供了支持,
    包括 Windows、Linux、BSD 和 macOS。
  • Nim 的内存管理是确定性的,可使用析构函数和移动语义进行自定义, 其灵感来自C++和Rust。 非常适合嵌入式硬实时系统。
  • 零开销迭代器和用户自定义方法的编译期求值等现代概念,
    结合优先使用分配在栈上的值类型数据,生成高性能代码。
  • 支持各种后端:可以被编译为 C、C++ 或 JavaScript, 以便 Nim 可用于所有后端和前端需求。

表现力

  • Nim 实现了自举:编译器和标准库都是用 Nim 本身来实现的。
  • Nim 拥有强大的宏系统,允许直接操纵 AST,提供无限的可能性。

优雅

  • 宏不会改变 Nim 的语法,因为并没有这个必要
    —— Nim 语法本身已经足够灵活。
  • 具有局部类型推断、元组、泛型和sum类型的现代类型系统。
  • 语句按缩进分组,也可以跨行。
import std/strformat

type
  Person = object
    name: string
    age: Natural # Ensures the age is positive

let people = [
  Person(name: "John", age: 45),
  Person(name: "Kate", age: 30)
]

for person in people:
  # Type-safe string interpolation,
  # evaluated at compile time.
  echo(fmt"{person.name} is {person.age} years old")


# Thanks to Nim's 'iterator' and 'yield' constructs,
# iterators are as easy to write as ordinary
# functions. They are compiled to inline loops.
iterator oddNumbers[Idx, T](a: array[Idx, T]): T =
  for x in a:
    if x mod 2 == 1:
      yield x

for odd in oddNumbers([3, 6, 9, 12, 15, 18]):
  echo odd


# Use Nim's macro system to transform a dense
# data-centric description of x86 instructions
# into lookup tables that are used by
# assemblers and JITs.
import macros, strutils

macro toLookupTable(data: static[string]): untyped =
  result = newTree(nnkBracket)
  for w in data.split(';'):
    result.add newLit(w)

const
  data = "mov;btc;cli;xor"
  opcodes = toLookupTable(data)

for o in opcodes:
  echo o
var conditional = 42

if conditional < 0:
  echo "conditional < 0"
elif conditional > 0:
  echo "conditional > 0"
else:
  echo "conditional == 0"

var ternary = if conditional == 42: true else: false

var another =
  if conditional == 0:
    "zero"
  elif conditional mod 2 == 0:
    "even"
  else:
    "odd"


# Case switch.
var letter = 'c'

case letter
of 'a':
  echo "letter is 'a'"
of 'b', 'c':
  echo "letter is 'b' or 'c'"
of 'd'..'h':
  echo "letter is between 'd' and 'h'"
else:
  echo "letter is another character"
import std/math

# Basic math.
assert 1 + 2 == 3        # Sum
assert 4 - 1 == 3        # Subtraction
assert 2 * 2 == 4        # Multiplication
assert 4 / 2 == 2.0      # Division
assert 4 div 2 == 2      # Integer Division
assert 2 ^ 3 == 8        # Power
assert 4 mod 2 == 0      # Modulo
assert (2 xor 4) == 6    # XOR
assert (4 shr 2) == 1    # Shift Right
assert PI * 2 == TAU     # PI and TAU
assert sqrt(4.0) == 2.0  # Square Root
assert round(3.5) == 4.0 # Round
assert isPowerOfTwo(16)  # Powers of Two
assert floor(2.9) == 2.0 # Floor
assert ceil(2.9) == 3.0  # Ceil
assert cos(TAU) == 1.0   # Cosine
assert gcd(12, 8) == 4   # Greatest common divisor
assert trunc(1.75) == 1.0     # Truncate
assert floorMod(8, 3) == 2    # Floor Modulo
assert floorDiv(8, 3) == 2    # Floor Division
assert hypot(4.0, 3.0) == 5.0 # Hypotenuse
assert gamma(4.0) == 6.0      # Gamma function
assert radToDeg(TAU) == 360.0 # Radians to Degrees
assert clamp(1.4, 0.0 .. 1.0) == 1.0 # Clamp
assert almostEqual(PI, 3.14159265358979)
assert euclDiv(-13, -3) == 5  # Euclidean Division
assert euclMod(-13, 3) == 2   # Euclidean Modulo
import std/[strutils, strscans]

assert "con" & "cat" == "concat"
assert "    a    ".strip == "a"
assert "42".parseInt == 42
assert "3.14".parseFloat == 3.14
assert "0x666".parseHexInt == 1638
assert "TrUe".parseBool == true
assert "0o777".parseOctInt == 511
assert "a".repeat(9) == "aaaaaaaaa"
assert "abc".startsWith("ab")
assert "abc".endsWith("bc")
assert ["a", "b", "c"].join == "abc"
assert "abcd".find("c") == 2
assert "a x a y a z".count("a") == 3
assert "A__B__C".normalize == "abc"
assert "a,b".split(",") == @["a", "b"]
assert "a".center(5) == "  a  "
assert "a".indent(4) == "    a"
assert "    a".unindent(4) == "a"

for word in tokenize("This is an example"):
  echo word

let (ok, year, month, day) = scanTuple("1000-01-01", "$i-$i-$i")
if ok:
  assert year == 1000
  assert month == 1
  assert day == 1
import std/[sugar, tables, sets, sequtils, strutils]

let variable0 = collect(newSeq):
  for item in @[-9, 1, 42, 0, -1, 9]:
    item * 2

assert variable0 == @[-18, 2, 84, 0, -2, 18]

let variable1 = collect(initTable):
  for key, value in @[0, 5, 9]:
    {key: value div 2}

assert variable1 == {0: 0, 1: 2, 2: 4}.toTable

let variable2 = collect(initHashSet):
  for item in @[-9, 1, 42, 0, -1, 9]:
    {item + item}

assert variable2 == [2, 18, 84, 0, -18, -2].toHashSet

assert toSeq(1..15).mapIt(
    if it mod 15 == 0:  "FizzBuzz"
    elif it mod 5 == 0: "Buzz"
    elif it mod 3 == 0: "Fizz"
    else: $it
  ).join(" ").strip == "1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz"

最新文章

Version 1.6.0 released

Nim version 1.6 is now officially released!

This Month with Nim: September 2021

Four interesting projects our users worked on in September

Nim in Action

第一本 Nim 图书,《Nim in Action》, 现已提供电子书或纸质书购买。 学习 Nim 的语法和高级功能(包括宏)等基础知识, 并通过多个应用程序开发示例获得该语言的实践经验。

  • 讲解基础知识,包括 Nim 的语法。
  • 说明如何使用 Nimble 包管理器。
  • 包括如何开发各种应用程序的分步说明和解释,涵盖了聊天程序,Twitter克隆等。

支持 Nim

加入支持 Nim 的100多家公司和个人

Nim 项目由一群分布在全球的志愿者开发。 我们欢迎捐款,这使我们能够花更多的时间工作在 Nim 上。

社区

在寻找 Nim 在GitHub上的存储库吗?

Nim 编译器和工具全部由 Nim 编写,并遵从MIT开源许可, 烦请务必对存储库点个 WATCH 以便及时获取 Nim 开发的最新进展,或者点个 Star 来给它提升一些关注。