Как оценить или выполнить интерполяцию строк в Elixir?

Предположим, я создаю строку, используя sigil_S:

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

Как мне заставить Эликсир оценить эту строку или выполнить интерполяцию, как если бы я ввел литерал "#{1 + 1}"?

Другими словами, как мне заставить его оценить значение "2"?

Я знаю, что вместо этого могу использовать EEx (например, EEx.eval_string "<%=1 + 1%>"), но мне любопытно, есть ли способ сделать это, используя только «простую» интерполяцию строк.


person Alistair A. Israel    schedule 14.09.2016    source источник


Ответы (3)


Символы нижнего регистра поддерживают интерполяцию. Подробнее об этом здесь:

Если сигил в нижнем регистре (например, 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"
person Vitalii Elenhaupt    schedule 14.09.2016
comment
Наверное, я не был так ясен в своем вопросе. Я знал о ~s. Во всяком случае, я смог сделать это, используя Code.eval_string ~s("#{s}") (обратите внимание на дополнительные кавычки). То, что я пытаюсь сделать, немного сложнее - по сути, я хочу иметь возможность делать то, что делает EEx.eval_string/3, но используя синтаксис интерполяции строк, например. my_eval ~S(Hello, #{name}), [name: "world"]. Code.eval_string ~s("Hello, #{name}") работает, когда имя определено, но Code.eval_string ~s("#{s}") не работает с undefined function name/0. Любые дальнейшие идеи? - person Alistair A. Israel; 14.09.2016
comment
Ах. Code.eval_string также принимает привязки. Я смог сделать то, что хотел, используя: Code.eval_string ~s("#{s}"), [name: "world"] - person Alistair A. Israel; 14.09.2016

Вы должны иметь возможность использовать модуль Code с функцией eval_string, поэтому просто замените EEx на Code.

Code.eval_string "1 + 1"
person PaReeOhNos    schedule 14.09.2016

Хотя вы можете использовать Code.eval_string/3:

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

слово «интерполяция», которое вы использовали в вопросе, наводит меня на мысль о том, что вы искали простое:

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

Sigil ~S экранирует< /a> задана строка, поэтому у вас экранировался знак диеза.

person Aleksei Matiushkin    schedule 14.09.2016