Nim:高效、优雅!


全网Quant都在看!



Nim是什么?


它是一种静态的、可编译的、面向对象的编程语言。

Nim被创建为一种速度与C一样快、表现能力与Python一样强、扩展能力与Lisp一样强的语言

。由于它的语法与Python相似,当你不喜欢C语言时,Nim是一个很好的选择。

安装地址:

https://nim-lang.org/install.html

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

同时这里还有很好的Nim学学习教程:

https://nim-lang.org/docs/tut1.html

看看有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:releasesome








 








checks 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 < 3:
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 < 3:
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还是不错的:

https://github.com/UNIcodeX/PCPC

为什么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 <stdio.h>

int fibonacci(int n) {
if (n <= 1) {
return n;
}
return fibonacci(n-1) + fibonacci(n-2);
}

int main(void) {
printf("%i", fibonacci(40));
}

Python代码:

def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(40))

Nim:

proc fibonacci(n: int): int = 
if n <= 1:
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 < 0: “negative”
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),很重视这块!先忙有一章专门介绍:

https://nim-lang.org/docs/tut3.html

示例:

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编写贪吃蛇,您可以试试!

https://picheta.me/snake/



量化投资与机器学习微信公众号,是业内垂直于

量化投资、对冲基金、
Fintech、人工智能、大数据




领域的
主流自媒体



公众号拥有来自

公募、私募、券商、期货、银行、保险、高校

等行业



20W+


关注者,连续2
年被腾讯云+社区评选为“年度最佳作者”。

量化投资与机器学习
我还没有学会写个人说明!
上一篇

科学家发现6.3亿年前的蘑菇祖先

你也可能喜欢

评论已经被关闭。

插入图片