5

In scala, you easily include the content of a variable inside a string, like this:

val nm = "Arrr"
println(s"my name is , $nm")

Is this possible in nim, and in that case, how?

Arrrrrrr
  • 802
  • 6
  • 13

3 Answers3

7

The strfmt module features some experimental string interpolation:

import strfmt
let nm = "Arrr"
echo interp"my name is $nm"
def-
  • 5,275
  • 20
  • 18
4

Adding your own string interpolation is not particularly had, since the standard library already provides most of the necessary pieces:

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
Grzegorz Adam Hankiewicz
  • 7,349
  • 1
  • 36
  • 78
  • That's a good custom solution. Could it work without variables initialized on compile time? – Arrrrrrr Apr 17 '15 at 19:24
  • One should mention that `interpolatedFragments` will break on something like `"${a & "}" & b}`, since it only counts braces. `strfmt` currently also suffers from this, but there should be a way to solve it by making `interpolatedFragments` a `compileTime` iterator, allowing to use `parseExpr` to properly parse an expression. – bluenote10 Apr 17 '15 at 19:49
  • @Arrrrrrr why wouldn't it? The macro doesn't do anything to variables, it only transforms the literals to break them up into concatenations. Added some "runtime" lines to example. – Grzegorz Adam Hankiewicz Apr 17 '15 at 20:38
  • @bluenote10 ``interpolatedFragments`` is very simple and wasn't intended for nested braces. Nothing stops you from implementing a brace escaping mechanism inside the parsing loop and making it on par to say an SQL parser like https://github.com/Araq/Nim/blob/devel/lib/pure/parsesql.nim. But at this point I'd say you are **abusing** string interpolation for little benefit. – Grzegorz Adam Hankiewicz Apr 17 '15 at 20:44
  • @GrzegorzAdamHankiewicz: What I'm trying to say is that since the macro is expanded at compile time, the full power of the compiler is available anyways, and it would make sense to use its expression parser (if possible!) instead of parsing it manually. Imho it is not an abuse to allow any possible language statement, just like you can in Scala. The problem with the limitations is not that they are overly restrictive, but that people will not know them and they will lose time to find out why they get strange compilation errors. – bluenote10 Apr 18 '15 at 08:50
0

The strformat module is now considered the go-to way to do it:

import strformat
let nm = "Arrr"
echo fmt"my name is , {nm}"
Saeed Baig
  • 1,197
  • 12
  • 13