我该如何在Elixir中评估或执行字符串插值?

5
假设我使用 sigil_S 构建一个字符串:
iex> s = ~S(#{1 + 1})
"\#{1 + 1}"

那么我该如何让 Elixir 来评估字符串或执行插值,就像我输入了字面量 "#{1 + 1}" 一样呢?

换句话说,我该如何让它评估为 "2" 呢?

我知道可以使用 EEx 来代替(例如:EEx.eval_string "<%=1 + 1%>"),但我很好奇是否有办法仅使用“普通”的字符串插值来实现。

3个回答

7

小写符号支持插值,更多信息见此

如果符号是小写的(例如sigil_x),则字符串参数将允许插值。如果符号是大写的(例如sigil_X),则字符串将不会进行插值。

因此,您可以使用符号~s来在原地评估插值:

~s(#{1 + 1}) #=> "2"
~S(#{1 + 1}) #=> "\#{1 + 1}"

或者您可以直接使用字符串插值:

"#{1 + 1}" #=> "2"

最后,如果您想动态评估写入字符串变量的代码,可以使用 Code.eval_string/3

s = "\"\#{1 + 1}\""               #=> "\"\#{1 + 1}\""
s |> Code.eval_string |> elem(0)  #=> "2"

我猜我的问题表述不够清楚。我知道 ~s 的用法。无论如何,我能够使用 Code.eval_string ~s("#{s}")(注意多余的引号)来实现这个目标。但是,我想做的事情有点复杂——本质上,我想要做到的是使用字符串插值语法来执行类似于 EEx.eval_string/3 的操作,例如 my_eval ~S(Hello, #{name}), [name: "world"]。当 name 被定义时,Code.eval_string ~s("Hello, #{name}") 可以正常工作,但 Code.eval_string ~s("#{s}") 则会失败,报错信息为“未定义 name/0 函数”。还有其他的想法吗? - Alistair A. Israel
2
啊,Code.eval_string 还可以接受绑定。我能够使用以下代码实现我想要的功能:Code.eval_string ~s("#{s}"), [name: "world"] - Alistair A. Israel
文档的新网址为:https://hexdocs.pm/elixir/Code.html - bortzmeyer

1
你应该能够使用Code模块,它具有eval_string函数,所以只需将EEx替换为Code
Code.eval_string "1 + 1"

1

虽然您可以使用 Code.eval_string/3

{result, _} = Code.eval_string "1 + 1"
result
#⇒ 2

你在问题中使用的“插值”一词让我认为你在寻找简单的方法:

"#{1 + 1}"
#⇒ "2"

Sigil ~S escapes the string given,这就是为什么你看到了井号被转义的原因。

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