Nim:高效、优雅!

发布于: 雪球转发:0回复:0喜欢:0

全网Quant都在看!

Nim是什么?

它是一种静态的、可编译的、面向对象的编程语言。Nim被创建为一种速度与C一样快、表现能力与Python一样强、扩展能力与Lisp一样强的语言。由于它的语法与Python相似,当你不喜欢C语言时,Nim是一个很好的选择。

安装地址:网页链接

在Nim官网,这段话概括了其强大的性能与特点:

同时这里还有很好的Nim学学习教程:网页链接

看看有Nim什么?

我们随便写一段程序:

打印num: 5 i: 5

1、变量声明

JavaScript程序员对它非常熟悉。虽然有些语言使用var,有些使用let,但JS和Nim都允许使用这两种语言中的任何一种声明。但是,需要注意的是,它们在两种语言中的含义并不相同。

2、块语法

为了在Nim中标记一个新语法块,使用冒号后跟一个缩进行,Python亦如此。

3、关键词

这两个循环以及if语句看起来和Python相差无几。实际上,第5行以后的所有代码实际上都是有效的 Python (假设我们定义了 echo 函数)。因此,Python中的许多关键词和操作符在Nim中也是有效的,比如not、is和or等。

看到这里,大家可能觉得Nim没有任何特别之处。从语法上来说,它看起来更糟糕(因为需要使用let或var)。

40th斐波那契数列测试结果:

在我们测试中注意到:通过简单地向Nim编译器传递一个flag,可以将其执行速度提高10倍以上。也有一些人做了测试,发现Nim甚至比C更快。正如官方文档中所述的:“By default the Nim compiler generates a large amount of runtime checks aiming for your debugging pleasure. With -d:releasesomechecks are turned off and optimizations are turned on.”

Nim预装了一个名为nimpy的模块,还有一个名为nimporter的模块可供Python使用。后者可以使用pip install nimporter安装。当这些语言一起工作时,这两个包将是必不可少的!

还是使用纳菲函数(Naifeh function)寻找斐波那契序列的第n个数字。

创建一个名为Benchmark的文件夹,里面有3个文件:

main.py:我们要运行的文件

nmath.nim:保存fib函数Nim版本的文件

pmath.py:保存fib函数Python版本的文件

首先,我们把fib函数写在pmath.py中:

def fib(n):
    if n == 0:
        return 0
    elif n         return 1
    return fib(n - 1) + fib(n - 2)

把目光转移到nmath.nim上:

import nimpy
proc fib(n: int): int {.exportpy.} =
    if n == 0:
        return 0
    elif n         return 1
    return fib(n-1) + fib(n-2)

使用proc关键字定义函数fib,将返回类型指定为整数。{.exportpy.}向Nim表示此函数将在另一个Python模块中使用。

在main.py中,我们将创建一个简单的benchmark

import nimporter
from time import perf_counter
import nmath # Nim imports!
import pmath
print('Measuring Python...')
start_py = perf_counter()
for i in range(0, 40):
    print(pmath.fib(i))
end_py = perf_counter()
print('Measuring Nim...')
start_nim = perf_counter()
for i in range(0, 40):
    print(nmath.fib(i))
end_nim = perf_counter()
print('---------')
print('Python Elapsed: {:.2f}'.format(end_py - start_py))
print('Nim Elapsed: {:.2f}'.format(end_nim - start_nim))

nimporter包将Nim导入解析到常规的Python模块中,以便像使用原生模块一样使用。很酷!

要运行这段代码,请在命令提示符中输入常用的python main.py命令:

Python Elapsed: 33.60
Nim Elapsed: 1.05

不过要记住,速度的差异可能取决于完成的任务。

根据Github用户测试的结果来看,Nim还是不错的:

网页链接

为什么Nim比Python快呢?

1、Nim是在解释Python的同时进行编译的。这意味着当Python程序运行时,要做的工作比仅仅运行程序还要多,因为在实际执行之前需要对程序进行解释。这通常会使语言变得很慢。

2、Nim是一种静态类型语言。对于动态类型的Python来说,解释器需要做更多的工作来找出并适当地处理类型,这也降低了执行速度。

下面是Python官方文档对解释型语言的解释:

“Interpreted languages typically have a shorter development/debug cycle than compiled ones, though their programs generally also run more slowly.”

这句话很好地总结了Python和C之间的博弈。你用Python做的事情,也可以用C做,但你程序的运行速度会快N个数量级。

然而,你将花费更多时间在的编写和调试代码上,而且代码将越长,可读性越差。这就是为什么C语言不再向之前那样流行,而Python却如此火爆的原因。简单地说:Python is easy(相对而言的easy)。

所以,如果Python是在这个范围的一端,而C在另一端,那么Nim试图在中间的某个地方:稍微快点,稍微容易点,哈哈~

然而,让Nim脱颖而出的是,乍一看,似乎把这种权衡最小化了。换句话说:它比Python快得多,但是不像C那样难于编程。

为了说明这一点,让我们看一下斐波那契实验中的代码。

C代码:

#include 
int fibonacci(int n) {
    if (n         return n;
    }
    return fibonacci(n-1) + fibonacci(n-2);
}
int main(void) {
    printf("%i", fibonacci(40));
}

Python代码:

def fibonacci(n):
    if n         return n
    return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(40))

Nim:

proc fibonacci(n: int): int =
    if n         return n
    return fibonacci(n-1) + fibonacci(n-2)
echo(fibonacci(40))

虽然Nim有proc,使用=来声明函数,但它仍然比C简洁很多!

未来可期

在2020年Stack Overflow的调查中,Nim甚至没有被提及。Stack Overflow标签上也只有427个问题:

与Python的150万相比,不值一提!

我们也可以认片面的认为大多数开发人员没有使用过它,而且很多人甚至从未听说过Nim这个名字。

老实说,Nim很酷的!

Nim能和Python抗衡吗?

目前来说,Nim还不足以挑战多才多艺的Python!

也有一些人告诉我们:Nim更适合从C++过渡的人,而不是从Python过渡的人!

Nim句法关键点的简要概述

更多的内容大家自行查看官。

1、变量

变量用var、let或const声明。

注意:虽然let在JavaScript作用域方面与var不同,但Nim表示一个变量,其值在初始化后不能更改。和Swift很像。

对于const,编译器必须在编译时确定值,而let可以在运行时确定。

文档案例:

const input = readLine(stdin) # Error: constant expression expected
let input = readLine(stdin) # works

此外,变量还么有这样声明:

var    a = 1
    b = 2
    c = 3
    x, y = 10 # Both x, y are assigned to 10

2、函数

Nim中的函数称为procedure,声明是这样执行的:

proc procedureName(parameterName: parameterType):returnType =
    return returnVar

也可使用=代替:

proc hello(s: string) = echo s

也可以像这样:

proc toString(x: int): string =
    result =
        if x         elif x > 0: “positive”
        else: “zero”

感觉上你还是应该return result,但result不是变量,而是关键词。上面的代码片段是完全有效的。

3、Control flow

对于在range上迭代,大家可以使用countup(start, finish),或者countdown(start, finish)而不是range。或者你可以简化整个事情并使用: for i in start..finish

4、宏

Nim支持宏和元编程(Metaprogramming),很重视这块!先忙有一章专门介绍:

网页链接

示例:

import macros
macro myMacro(arg: static[int]): untyped =
    echo arg
 
myMacro(1 + 2 * 3)

5、JavaScript编译

来自Nim官网:

“Nim includes a first-class JavaScript backend so you can target the client and server effortlessly at the same time.”

如果你想用Nim编写贪吃蛇,您可以试试!

网页链接

量化投资与机器学习微信公众号,是业内垂直于量化投资、对冲基金、Fintech、人工智能、大数据等领域的主流自媒体。公众号拥有来自公募、私募、券商、期货、银行、保险、高校等行业20W+关注者,连续2年被腾讯云+社区评选为“年度最佳作者”。