如何在 Nim 中的格式化字符串中使用表达式?

Ale*_*hin 4 nim-lang

if如果内部使用的表达是行不通的fmt字符串。

为什么,以及如何使它工作?

import strformat

let v = if true: 1 else: 2 # <= Works
echo fmt"{v}"

echo fmt"{if true: 1 else: 2}" # <= Error
Run Code Online (Sandbox Code Playgroud)

pie*_*ter 5

为什么?

因为fmt用于:将表达式的值与格式说明符分开,所以(请参阅文档实现)该行

echo fmt"{if true: 1 else: 2}"

被宏扩展为

var temp = newStringOfCap(educatedCapGuess)
temp.formatValue if true, " 1 else: 2"
temp
Run Code Online (Sandbox Code Playgroud)

这显然不能编译。

如何?

更新

目前(2021 年 4 月)在 devel 分支中有一项增强功能,允许在格式化字符串中使用任何表达式。对于提到的特定情况,您需要用括号将表达式括起来:

echo fmt"{(if true: 1 else: 2)}"
Run Code Online (Sandbox Code Playgroud)

新的增强功能还允许在表达式中使用大括号(转义它们)。

看:

此增强功能将在下一个稳定版本(可能是 1.6)中面向公众发布。

旧内容

我想这可以被看作是一个限制fmt,我不认为这是目前使用的表达方式:fmt那里不作为的格式specificier。

解决此问题的一种方法是提供额外的formatSpecifierSeparator关键字参数以更改默认值:并能够执行以下操作:

echo "{if true: 1 else: 2}".fmt('|')

另一种方法是更改​​实现strformatImpl并确保 a:之前的部分在解释:为 formatSpecifier 分隔符之前实际编译。

这两种方式都意味着 nim-lang 代码中的 PR,如果被接受和合并,将在下一个版本或开发后可用。


tim*_*our 5

这有效:

import std/strformat
let x = 3.14
assert fmt"{(if x!=0: 1.0/x else: 0):.5}" == "0.31847"
assert fmt"{(if true: 1 else: 2)}" == "1"
assert fmt"{if true\: 1 else\: 2}" == "1"
Run Code Online (Sandbox Code Playgroud)

并避免与格式说明符发生冲突。有关更多详细信息,请参阅https://github.com/nim-lang/Nim/pull/17700