字符串插值

5
在Scala中,您可以轻松地将变量内容嵌入字符串中,如下所示:
val nm = "Arrr"
println(s"my name is , $nm")

这在Nim中是否可能?如果是,怎么做?
3个回答

7

1
太棒了,这个真的应该包含在标准库中。 - bluenote10
我同意bluenote10的观点。谢谢def-。 - Arrrrrrr

4

添加自己的字符串插值并不特别困难,因为标准库已经提供了大部分必要的组件:

import macros, parseutils, sequtils

macro i(text: string{lit}): expr =
  var nodes: seq[PNimrodNode] = @[]
  # Parse string literal into "stuff".
  for k, v in text.strVal.interpolatedFragments:
    if k == ikStr or k == ikDollar:
      nodes.add(newLit(v))
    else:
      nodes.add(parseExpr("$(" & v & ")"))
  # Fold individual nodes into a statement list.
  result = newNimNode(nnkStmtList).add(
    foldr(nodes, a.infix("&", b)))

const
  multiplier = 3
  message = i"$multiplier times 2.5 is ${multiplier * 2.5}"

echo message
# --> 3 times 2.5 is 7.5

proc blurb(a: int): string =
  result = i"param a ($a) is not a constant"

when isMainModule:
  for f in 1..10:
    echo f.blurb

那是一个不错的自定义解决方案。如果在编译时没有初始化变量,它是否能工作? - Arrrrrrr
应该提到,interpolatedFragments 在类似 "${a & "}" & b}" 这样的字符串中会出现错误,因为它只计算大括号。strfmt 目前也存在这个问题,但可以通过将 interpolatedFragments 设为 compileTime 迭代器来解决,从而允许使用 parseExpr 来正确解析表达式。 - bluenote10
@Arrrrrrr 为什么不行呢?这个宏并不会对变量做任何操作,它只是将字面量转换成连接符以分解它们。在示例中添加了一些“运行时”行。 - Grzegorz Adam Hankiewicz
@bluenote10,“interpolatedFragments”非常简单,不打算嵌套大括号。在解析循环内部实现括号转义机制并将其与SQL解析器 https://github.com/Araq/Nim/blob/devel/lib/pure/parsesql.nim 相媲美完全没有问题。但是目前我要说的是,您正在误用字符串插值而无法获得太多好处。 - Grzegorz Adam Hankiewicz
@GrzegorzAdamHankiewicz:我的意思是,由于宏在编译时展开,因此编译器的全部功能都可用,如果可能的话,使用其表达式解析器(如果可能!)而不是手动解析它是有意义的。我认为允许任何可能的语言语句并不是滥用,就像在Scala中一样。限制的问题不在于它们过于严格,而在于人们不知道它们,他们将浪费时间找出为什么会出现奇怪的编译错误。 - bluenote10

0

strformat模块现在被认为是最佳实践:

import strformat
let nm = "Arrr"
echo fmt"my name is , {nm}"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接