Julia Language
Строковые макросы
Поиск…
Синтаксис
- макрос «строка» # короткая, строковая макроформа
- @macro_str "string" # long, регулярная макроформа
- macro`command`
замечания
Макросы String не так сильны, как простые старые строки - поскольку интерполяция должна быть реализована в логике макроса, макросы строк не могут содержать строковые литералы одного и того же разделителя для интерполяции.
Например, хотя
julia> "$("x")"
"x"
работает, текстовая форма строки
julia> doc"$("x")"
ERROR: KeyError: key :x not found
неправильно анализируется. Это можно несколько смягчить, используя тройные кавычки в качестве внешнего ограничителя строк;
julia> doc"""$("x")"""
"x"
действительно работает правильно.
Использование строковых макросов
Макросы строк - это синтаксический сахар для определенных макросов. Синтаксический анализатор расширяет синтаксис как
mymacro"my string"
в
@mymacro_str "my string"
который затем, как и любой другой макрокоманд, заменяется любым выражением, возвращаемым макросом @mymacro_str
. База Julia поставляется с несколькими строковыми макросами, такими как:
@b_str
Этот строковый макрос строит байтовые массивы вместо строк . Содержимое строки, закодированной как UTF-8, будет использоваться как массив байтов. Это может быть полезно для взаимодействия с низкоуровневыми API-интерфейсами, многие из которых работают с байтовыми массивами вместо строк.
julia> b"Hello World!"
12-element Array{UInt8,1}:
0x48
0x65
0x6c
0x6c
0x6f
0x20
0x57
0x6f
0x72
0x6c
0x64
0x21
@big_str
Этот макрос вернет BigInt
или BigFloat
проанализированный из строки, которую он дал.
julia> big"1"
1
julia> big"1.0"
1.000000000000000000000000000000000000000000000000000000000000000000000000000000
Этот макрос существует, потому что big(0.1)
не ведет себя так, как изначально ожидалось: 0.1
- это аппроксимация Float64
истины 0.1
( 1//10
), и продвижение этого BigFloat
в BigFloat
будет поддерживать ошибку аппроксимации Float64
. Использование макроса будет анализировать 0.1
непосредственно на BigFloat
, уменьшая погрешность аппроксимации.
julia> big(0.1)
1.000000000000000055511151231257827021181583404541015625000000000000000000000000e-01
julia> big"0.1"
1.000000000000000000000000000000000000000000000000000000000000000000000000000002e-01
@doc_str
Этот строковый макрос Base.Markdown.MD
объекты Base.Markdown.MD
, которые используются во внутренней документации для предоставления полнотекстовой документации для любой среды. Эти объекты MD хорошо отображаются в терминале:
а также в браузере:
@html_str
Этот строковый макрос создает строковые литералы HTML, которые хорошо отображаются в браузере:
@ip_str
Этот строковый макрос создает литералы IP-адреса. Он работает как с IPv4, так и с IPv6:
julia> ip"127.0.0.1"
ip"127.0.0.1"
julia> ip"::"
ip"::"
@r_str
Этот строковый макрос Regex
литералы Regex
.
@s_str
Этот строковый макрос SubstitutionString
литералы SubstitutionString
, которые работают вместе с литералами Regex
чтобы обеспечить более продвинутую текстовую замену.
@text_str
Этот строковый макрос похож по духу на @doc_str
и @html_str
, но не имеет каких-либо причудливых особенностей форматирования:
@v_str
Этот макрос строк VersionNumber
литералы VersionNumber
. См. Номера версий для описания того, что они есть и как их использовать.
@MIME_str
Этот строковый макрос создает однотипные типы MIME-типов. Например, MIME"text/plain"
- это тип MIME("text/plain")
.
Символы, которые не являются юридическими идентификаторами
Литералы Джулии Символы должны быть юридическими идентификаторами. Это работает:
julia> :cat
:cat
Но это не так:
julia> :2cat
ERROR: MethodError: no method matching *(::Int64, ::Base.#cat)
Closest candidates are:
*(::Any, ::Any, ::Any, ::Any...) at operators.jl:288
*{T<:Union{Int128,Int16,Int32,Int64,Int8,UInt128,UInt16,UInt32,UInt64,UInt8}}(::T<:Union{Int128,Int16,Int32,Int64,Int8,UInt128,UInt16,UInt32,UInt64,UInt8}, ::T<:Union{Int128,Int16,Int32,Int64,Int8,UInt128,UInt16,UInt32,UInt64,UInt8}) at int.jl:33
*(::Real, ::Complex{Bool}) at complex.jl:180
...
То, что похоже на буквенный символ здесь, фактически анализируется как неявное умножение :2
(это всего лишь 2
) и функция cat
, которая, очевидно, не работает.
Мы можем использовать
julia> Symbol("2cat")
Symbol("2cat")
для решения этой проблемы.
Строковый макрос может помочь сделать это более кратким. Если мы определяем макрос @sym_str
:
macro sym_str(str)
Meta.quot(Symbol(str))
end
то мы можем просто сделать
julia> sym"2cat"
Symbol("2cat")
для создания символов, которые не являются действительными идентификаторами Юлии.
Конечно, эти методы также могут создавать символы, которые являются действительными идентификаторами Юлии. Например,
julia> sym"test"
:test
Реализация интерполяции в строковом макросе
Макросы String не оснащены встроенными средствами интерполяции . Тем не менее, это можно реализовать вручную. Обратите внимание, что невозможно вставлять без экранирования строковых литералов, которые имеют тот же разделитель, что и окружающий строковый макрос; то есть, хотя возможно """ $("x") """
, " $("x") "
нет. Вместо этого это должно быть экранировано как " $(\"x\") "
. Дополнительную информацию об этом ограничении см. В разделе примечаний .
Существует два подхода к внедрению интерполяции вручную: реализовать парсинг вручную или заставить Джулию выполнять синтаксический анализ. Первый подход более гибкий, но второй подход проще.
Ручной анализ
macro interp_str(s)
components = []
buf = IOBuffer(s)
while !eof(buf)
push!(components, rstrip(readuntil(buf, '$'), '$'))
if !eof(buf)
push!(components, parse(buf; greedy=false))
end
end
quote
string($(map(esc, components)...))
end
end
Анализ Юлии
macro e_str(s)
esc(parse("\"$(escape_string(s))\""))
end
Этот метод экранирует строку (но учтите , что escape_string
не избежать $
знаков) и передает его обратно в синтаксический анализатор Джулии разобрать. Экранирование строки необходимо для обеспечения того, чтобы "
и \
не влияли на синтаксический анализ строки. Полученное выражение представляет собой :string
выражение, которое можно анализировать и разлагать для целей макроса.
Командные макросы
В Julia v0.6 и более поздних версиях макросы команд поддерживаются в дополнение к регулярным строковым макросам. Вызов макроса команды, например
mymacro`xyz`
анализируется как вызов макроса
@mymacro_cmd "xyz"
Обратите внимание, что это похоже на строковые макросы, за исключением _cmd
вместо _str
.
Обычно мы используем команду макросы для кода, который во многих языках часто содержит "
, но редко содержит `
Например, это довольно просто переописать простой вариант. Quasiquoting с помощью команды макросов:
macro julia_cmd(s)
esc(Meta.quot(parse(s)))
end
Мы можем использовать этот макрос либо inline:
julia> julia`1+1`
:(1 + 1)
julia> julia`hypot2(x,y)=x^2+y^2`
:(hypot2(x,y) = begin # none, line 1:
x ^ 2 + y ^ 2
end)
или многострочный:
julia> julia```
function hello()
println("Hello, World!")
end
```
:(function hello() # none, line 2:
println("Hello, World!")
end)
Поддерживается интерполяция с использованием $
:
julia> x = 2
2
julia> julia`1 + $x`
:(1 + 2)
но приведенная здесь версия допускает только одно выражение:
julia> julia```
x = 2
y = 3
```
ERROR: ParseError("extra token after end of expression")
Однако расширить его для обработки нескольких выражений не сложно.