皇上,还记得我吗?我就是1999年那个Linux伊甸园啊-----24小时滚动更新开源资讯,全年无休!

Nim 语言 1.2 版本发布!向后兼容性增强和新的宏

以下由中文社区翻译,能力有限,如有翻译错误,欢迎指正!

在持续六个月的开发后,我们骄傲地宣布,Nim 1.2 版本发布了!

本发行版包含了超过 600 次的尚未被合并到 1.0.x 版本的提交。 与 1.0 相比,添加了几个新功能和标准库。 我们努力将断崖式的改动降至最低, 但如果不进行这些必要的更改,某些错误是无法被修复的, 而且我们认为我们的用户将从中受益。

我们建议所有用户升级和使用 1.2 版本。

使用多个版本的 Nim

useVersion

如果你想要更新到 v1.2 版本,但依赖与 v1.0 版本的一些行为, 你可以使用命令行参数 --useVersion 来切换。 在最新的 Nim 中,你可以用这个参数来模拟之前版本的 Nim 。

举个例子,v1.2 版本的 Nim 对 proc 类型的类型转换变得更加严格。 如果这个变更无法兼容你的代码,你可以使用 --useVersion:1.0 来模拟之前版本的行为。

上面的例子只是个示例。 如果你依赖于一些边缘案例,或现已修复的错误行为,试试 --useVersion:1.0 ,他可能返回你想看到的结果。

如果没有得到你想要的之前版本的行为,请打开在 我们的 bug 追踪器 上提个 issue , 我们会努力在未来的 bug 修复版本(1.2.x)中进行修复。

when declared

如果你开发了 Nim 的库,而且想让不管是用 v1.0 的还是 v1.2 版本的用户都能使用你的库, 但却依赖了一些在 v1.0 版本没有,而在 v1.2 版本中才加入的新特性, 你可以使用 when declared 作为你的优势。

举个例子, sequtils 模块现在加入了 unzip 过程。 你就可以把你的代码写成下面这样:

import sequtils

when not declared(unzip):
  proc unzip*[S, T](s: openArray[(S, T)]): (seq[S], seq[T]) =
    result[0] = newSeq[S](s.len)
    result[1] = newSeq[T](s.len)
    for i in 0..<s.len:
      result[0][i] = s[i][0]
      result[1][i] = s[i][1]

let a = @[('a', 1), ('b', 2), ('c', 3)]
let b = unzip(a) # version 1.0 将会使用上方声明的过程
                 # version 1.2 会直接使用 sequtils 模块的过程

assert b == (@['a', 'b', 'c'], @[1, 2, 3])

安装 Nim 1.2

Nim 的新用户

检查你系统的包管理器是否已经装载了 1.2 版本, 或者按照 这里 的说明进行安装。

老用户

如果你之前使用 choosenim 安装过老版本的 Nim , 升级到 1.2 版本就这么简单:

$ choosenim update stable

为 v1.2 贡献力量

我们的贡献者都是超人, 我们列举了很多到 这里。 给你们个大大的么么哒,没有你们就没有这个版本!

新特性

GC: ARC

我们这次版本主要的新特性是 --gc:arc !

为了避免陷入本文中大量的细节, 我们建议你查看下 FOSDEM上的这个视频(YouTuBe), Araq 在视频中解释了 ARC 背后的详细信息,并展示了一些显示其优点的基准。 之后可能会更新一篇关于 ARC 详细说明的文章。

新的宏语法糖

1.2.0 版本介绍了一些新的宏,它们应该可以帮你完成一些通用的任务。

在接下来的一些章节中,我们会给你展示他们和他们的用例。 所有的示例都意味着 import sugar

Collect

collect 是一个用以解析序列/集合/表解析的宏。 它替代了 lc (list comprehension,列表解析), 而且比 lc 更人性化和强大。 使用 collect 没有开销,比如说:你可以把 newSeqOfCap 和它配合使用。

所有集合的语法都是类似的,区别在于 init 函数和最后一个表达式。

举个例子:

let numbers = collect(newSeq):  # 或者: collect(newSeqOfCap(10))
  for i in 1..10:
    i

assert numbers == @[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


import tables
let oddSquares = collect(initTable):
  for i in numbers:
    if i mod 2 == 1:
      {i: i * i}

assert len(oddSquares) == 5
assert oddSquares[7] == 49


import sets
let oddOrNegative = collect(initHashSet):
  for i in numbers:
    {if i mod 2 == 1: i else: -i}

assert 5 in oddOrNegative
assert 2 notin oddOrNegative
assert -2 in oddOrNegative

Dup

dup 是一个宏,它让原地函数(in-place functions,译者注:引用传递参数的函数) 可以在不影响和修改函数输入的情况下返回结果。

我们是这么考虑的,Nim的未来版本将只提供函数的原地版本 (即不再提供 sort 和 sortedrotateLeft 和 rotatedLeft 等), 他们可以被 dup 转换为返回拷贝的函数。 这些版本可以通过 dup 转换成返回副本的函数。

这个宏也允许了(其他方式的)函数链(function chaining)。

还是看示例吧:

proc makePalindrome(s: var string) =
  for i in countdown(s.len-2, 0):
    s.add(s[i])

var a = "abc"
makePalindrome(a)
assert a == "abcba"

var b = "xyz"
var c = b.dup(makePalindrome)

assert b == "xyz"
assert c == "xyzyx"

下划线(_)可用于表示传递参数的位置:

import algorithm

# b = "xyz"
var d = dup b:
  makePalindrome  # xyzyx
  sort(_, SortOrder.Descending)  # zyyxx
  makePalindrome  # zyyxxxyyz

assert d == "zyyxxxyyz"

Capture

capture 是一个宏,在循环中创建闭包时非常有用, 以捕获一些局部循环变量(按其当前迭代值)。 您可能希望将其用于事件处理和 {int: callBack} 查找表。‎

举例如下:

import strformat, sugar

var myClosure: proc(): string

for i in 5..7:
  for j in 7..9:
    if i * j == 42:
      capture i, j:
        myClosure = proc (): string = fmt"{i} * {j} = 42"

let a = myClosure()
assert a == "6 * 7 = 42"

转自 https://www.oschina.net/news/114765/nim-1-2-released