您现在的位置是:首页 > 文章详情

Nim 发布1.6.0 版本,命令式编程语言

日期:2021-10-22点击:948

Nim 是一门专注于性能、可移植性和表现力的系统编程语言。经过一年的厚积薄发,Nim 1.6.0 稳定版已正式发布。

主要更新内容如下:

向后兼容性和预览标志

1.6 版本引入了 -d:nimPreviewX 这种形式的预览标志(例如 -d:nimPreviewFloatRoundtrip ),这种标志允许用户选择加入新的标准库/编译器行为,加入这些标志是为了尽量减少向后兼容性问题。

1.6 还引入了 -d:nimLegacyX 形式的退出标志,例如 -d:nimLegacyCopyFile 。如果你在用老版本的 Nim ,可以用这些标志来适配老版本的语法。 以下是 1.6 版本中引入的所有标志,可以结合后面的新功能介绍了解它们的具体用法。

  • -d:nimLegacyCopyFile
  • -d:nimLegacyJsRound
  • -d:nimLegacyMacrosCollapseSymChoice
  • -d:nimLegacyParseQueryStrict
  • -d:nimLegacyRandomInitRand
  • -d:nimLegacyReprWithNewline
  • -d:nimLegacySigpipeHandler
  • -d:nimLegacyTypeMismatch
  • -d:nimPreviewDotLikeOps
  • -d:nimPreviewFloatRoundtrip
  • -d:nimPreviewHashRef
  • -d:nimPreviewJsonutilsHoleyEnum

主要的新功能:

  • iterable[T]

加入了 iterable[T] type 类来匹配被调用的迭代器,例子:

 iterator iota(n: int): int = for i in 0..<n: yield i # 以前需要用“untyped”,这会导致其他问题,比如缺乏类型推断、重载问题和 MCS template sumOld(a: untyped): untyped = # 不可能有类型推断 var result: typeof(block:(for ai in a: ai)) for ai in a: result += ai result assert sumOld(iota(3)) == 0 + 1 + 2 # 现在,你可以写成: template sum[T](a: iterable[T]): T = # 也可以写成:`template sum(a: iterable): auto =` var result: T for ai in a: result += ai result assert sum(iota(3)) == 0 + 1 + 2 # or `iota(3).sum` 

更重要的是,现在可迭代参数能和方法调用的语句一起使用了:

 import std/[sequtils, os] echo walkFiles("*").toSeq # now works

关于 iterable[T] 的详细信息,请查看 #17196

  • 严谨的效果

效果系统得到了改进,并且有一个新的 .effectsOf 注释,它可以显式地完成之前隐式完成的工作,更多详细信息请参阅手册

如果你仍要编写老版本 Nim 的代码,请使用以下用法:

 when defined(nimHasEffectsOf): {.experimental: "strictEffects".} else: {.pragma: effectsOf.} proc mysort(s: seq; cmp: proc(a, b: T): int) {.effectsOf: cmp.}

要启用新的效果系统,请使用 --experimental:strictEffects 进行编译。详情可查看 #18777和 RFC #408

  • 私有导入和私有字段访问

新的导入语句 import foo {.all.} 允许从 foo 里面导入所有符号(无论是私有的还是公开的),这点对于测试或者项目的灵活性都很有帮助,

比如:

 from system {.all.} as system2 import nil echo system2.ThisIsSystem # ThisIsSystem is private in `system` import os {.all.} # weirdTarget is private in `os` echo weirdTarget # or `os.weirdTarget`

添加了一个新模块 std/importutils和一个 API privateAccess,它允许访问当前作用域对象类型的私有字段。

比如:

 import times from std/importutils import privateAccess block: let t = now() # echo t.monthdayZero # Error: undeclared field: 'monthdayZero' for type times.DateTime privateAccess(typeof(t)) # enables private access in this scope echo t.monthdayZero # ok

更多细节请查看 PR #17706

  • nim --eval:cmd

加入 nim --eval:cmd 来直接计算命令,比如 nim --eval:"echo 1" 。它默认为 e (nimscript)。也可以跟其他命令一起用,例如:

 find . | nim r --eval:'import strutils; for a in stdin.lines: echo a.toUpper' # use as a calculator: nim --eval:'echo 3.1 / (1.2+7)' # explore a module's APIs, including private symbols: nim --eval:'import os {.all.}; echo weirdTarget' # use a custom backend: nim r -b:js --eval:"import std/jsbigints; echo 2'big ** 64'big"

更多详细信息,请查看PR #15687

  • 浮点数和字符串的相互转换

system.addFloat system.$ 能将浮点数转化成字符串形式,通过 Dragonbox 算法实现了这些特性:最小规格、可以相互转换、正确的位数舍入。例如:

 from math import round let a = round(9.779999999999999, 2) assert a == 9.78 echo a # with `-d:nimPreviewFloatRoundtrip`: 9.78, like in python3 (instead of 9.779999999999999)

目前只能通过 -d:nimPreviewFloatRoundtrip 开启这个功能,后面的版本可能会把这个设置成默认功能。

  • 新模块:std/jsbigints

为 JS 目标提供任意精度的整数,详见 PR #16409。例如:

 import std/jsbigints assert 2'big ** 65'big == 36893488147419103232'big echo 0xdeadbeef'big shl 4'big # 59774856944n
  • 新模块:std/sysrand

用于加密安全的伪随机数生成器,允许从操作系统提供的安全源生成随机数。详见 PR #16459。例子:

 import std/sysrand assert urandom(1234) != urandom(1234) # unlikely to fail in practice
  • 新模块:std/tempfiles

允许创建临时文件和目录,详见 PR #17361

 import std/tempfiles let tmpPath = genTempPath("prefix", "suffix.log", "/tmp/") # tmpPath looks like: /tmp/prefixpmW1P2KLsuffix.log let dir = createTempDir("tmpprefix_", "_end") # created dir looks like: getTempDir() / "tmpprefix_YEl9VuVj_end" let (cfile, path) = createTempFile("tmpprefix_", "_end.tmp") # path looks like: getTempDir() / "tmpprefix_FDCIRZA0_end.tmp" cfile.write "foo" cfile.setFilePos 0 assert readAll(cfile) == "foo" close cfile assert readFile(path) == "foo"
  • 用户自定义字面量

现在支持用户自定义数字型的字面值 (例如 -128'bignum ),除此之外,-1 里面的负号也会作为整形字面常量的一部分被单个解析,这意味着像 -128'i8 这样的边界案例也可以正常运行了,看一个例子:

 func `'big`*(num: cstring): JsBigInt {.importjs: "BigInt(#)".} assert 0xffffffffffffffff'big == (1'big shl 64'big) - 1'big
  • 点状运算符

使用 -d:nimPreviewDotLikeOps 的时候,点状运算符 . 的优先级一模一样了,所以 a.?b.c 现在会解析成(a.?b).c ,而不是 a.?(b.c)。如果不是在 -d:nimPreviewDotLikeOps 的情况下使用点状运算符,就会出现警告

建议启用动态字段,比如 std/jsffi, std/json, pkg/nimpy而不是影响内置的点状运算符 .。看这个例子:

 import std/json template `.?`(a: JsonNode, b: untyped{ident}): JsonNode = a[astToStr(b)] let j = %*{"a1": {"a2": 10}} assert j.?a1.?a2.getInt == 10
  • Block 参数可以选择形参

解决了接受 Block 参数的主要痛点,详见 PR #18631

 template fn(a = 1, b = 2, body) = discard fn(1, 2): # already works bar fn(a = 1): # now works bar

多个 block 参数可以用 do 来实现:

 template fn(a = 1, b = 2, body1, body2) = discard fn(a = 1): # now works bar1 do: bar2

其他特性

查看完整版更新日志,请点击这里

 

更新公告:https://nim-lang.org/blog/2021/10/19/version-160-released.html

原文链接:https://www.oschina.net/news/165453/nim-1-6-0-released
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章