Julia Language
Macros de cadena
Buscar..
Sintaxis
- macro "cadena" # breve, forma de macro de cadena
- @macro_str "cadena" # larga, forma de macro regular
- macro`command`
Observaciones
Las macros de cadena no son tan poderosas como las cadenas simples, ya que la interpolación debe implementarse en la lógica de la macro, las macros de cadena no pueden contener literales de cadena del mismo delimitador para la interpolación.
Por ejemplo, aunque
julia> "$("x")"
"x"
funciona, la cadena de texto forma macro
julia> doc"$("x")"
ERROR: KeyError: key :x not found
se analiza incorrectamente. Esto se puede mitigar de alguna manera usando comillas triples como delimitador de cadena externo;
julia> doc"""$("x")"""
"x"
de hecho funciona correctamente.
Usando macros de cuerdas
Las macros de cadena son azúcar sintáctica para ciertas invocaciones de macro. El analizador expande la sintaxis como
mymacro"my string"
dentro
@mymacro_str "my string"
que luego, como cualquier otra llamada de macro, se sustituye por cualquier expresión que @mymacro_str
macro @mymacro_str
. Base Julia viene con varias macros de cuerdas, tales como:
@b_str
Esta macro de cadena construye matrices de bytes en lugar de cadenas . El contenido de la cadena, codificado como UTF-8, se utilizará como la matriz de bytes. Esto puede ser útil para interactuar con las API de bajo nivel, muchas de las cuales funcionan con matrices de bytes en lugar de cadenas.
julia> b"Hello World!"
12-element Array{UInt8,1}:
0x48
0x65
0x6c
0x6c
0x6f
0x20
0x57
0x6f
0x72
0x6c
0x64
0x21
@big_str
Esta macro devolverá un BigInt
o un BigFloat
analizado de la cadena que se proporciona.
julia> big"1"
1
julia> big"1.0"
1.000000000000000000000000000000000000000000000000000000000000000000000000000000
Esta macro existe porque big(0.1)
no se comporta como se podría esperar inicialmente: 0.1
es una aproximación de Float64
de 0.1
( 1//10
), y promoverla a BigFloat
mantendrá el error de aproximación de Float64
. El uso de la macro analizará 0.1
directamente a un BigFloat
, reduciendo el error de aproximación.
julia> big(0.1)
1.000000000000000055511151231257827021181583404541015625000000000000000000000000e-01
julia> big"0.1"
1.000000000000000000000000000000000000000000000000000000000000000000000000000002e-01
@doc_str
Esta macro de cadena construye objetos Base.Markdown.MD
, que se utilizan en el sistema de documentación interno para proporcionar documentación de texto enriquecido para cualquier entorno. Estos objetos MD se reproducen bien en un terminal:
y también en un navegador:
@html_str
Esta macro de cadena construye literales de cadena HTML, que se reproducen bien en un navegador:
@ip_str
Esta macro de cadena construye literales de dirección IP. Funciona tanto con IPv4 como con IPv6:
julia> ip"127.0.0.1"
ip"127.0.0.1"
julia> ip"::"
ip"::"
@r_str
Esta macro de cadena construye Regex
literales .
@s_str
Esta macro de cadena construye los literales SubstitutionString
, que funcionan junto con los literales Regex
para permitir una sustitución textual más avanzada.
@text_str
Esta macro de cadena es similar en espíritu a @doc_str
y @html_str
, pero no tiene ninguna característica de formato de fantasía:
@v_str
Esta macro de cadena construye los literales de VersionNumber
. Consulte Números de versión para obtener una descripción de qué son y cómo usarlos.
@MIME_str
Esta macro de cadena construye los tipos singleton de tipos MIME. Por ejemplo, MIME"text/plain"
es el tipo de MIME("text/plain")
.
Símbolos que no son identificadores legales
Los literales de Julia Symbol deben ser identificadores legales. Esto funciona:
julia> :cat
:cat
Pero esto no lo hace:
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
...
Lo que parece un símbolo literal aquí en realidad se analiza como una multiplicación implícita de :2
(que es solo 2
) y la función cat
, que obviamente no funciona.
Nosotros podemos usar
julia> Symbol("2cat")
Symbol("2cat")
para solucionar el problema.
Una macro de cadena podría ayudar a hacer esto más conciso. Si definimos la macro @sym_str
:
macro sym_str(str)
Meta.quot(Symbol(str))
end
entonces podemos simplemente hacer
julia> sym"2cat"
Symbol("2cat")
Para crear símbolos que no sean identificadores de Julia válidos.
Por supuesto, estas técnicas también pueden crear símbolos que son identificadores de Julia válidos. Por ejemplo,
julia> sym"test"
:test
Implementando interpolación en una macro de cadena
Las macros de cadenas no vienen con instalaciones de interpolación incorporadas. Sin embargo, es posible implementar manualmente esta funcionalidad. Tenga en cuenta que no es posible incrustar sin escapar literales de cadena que tienen el mismo delimitador que la macro de cadena circundante; es decir, aunque """ $("x") """
es posible, " $("x") "
no lo es. En su lugar, esto debe escaparse como " $(\"x\") "
. Consulte la sección de comentarios para obtener más detalles sobre esta limitación.
Hay dos enfoques para implementar la interpolación manualmente: implementar el análisis manualmente, o hacer que Julia haga el análisis. El primer enfoque es más flexible, pero el segundo es más fácil.
Análisis manual
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
Julia analizando
macro e_str(s)
esc(parse("\"$(escape_string(s))\""))
end
Este método escapa de la cadena (pero tenga en cuenta que escape_string
no escapa de los signos $
) y se lo pasa al analizador de Julia para analizarlo. El escape de la cadena es necesario para garantizar que "
y \
no afecten el análisis de la cadena. La expresión resultante es una :string
expresión de :string
, que se puede examinar y descomponer para propósitos de macro.
Macros de comando
En Julia v0.6 y versiones posteriores, las macros de comandos son compatibles además de las macros de cadena normales. Una invocación de macro de comando como
mymacro`xyz`
se analiza como la llamada macro
@mymacro_cmd "xyz"
Tenga en cuenta que esto es similar a las macros de cadenas, excepto con _cmd
lugar de _str
.
Utilizamos típicamente macros de comando de código, que en muchos idiomas con frecuencia contiene "
pero rara vez contiene `
Por ejemplo, es bastante sencillo volver a implementar una versión simple de. Quasiquoting usando macros de comando:
macro julia_cmd(s)
esc(Meta.quot(parse(s)))
end
Podemos usar esta macro ya sea en línea:
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)
o multilínea:
julia> julia```
function hello()
println("Hello, World!")
end
```
:(function hello() # none, line 2:
println("Hello, World!")
end)
Se admite la interpolación usando $
julia> x = 2
2
julia> julia`1 + $x`
:(1 + 2)
pero la versión dada aquí solo permite una expresión:
julia> julia```
x = 2
y = 3
```
ERROR: ParseError("extra token after end of expression")
Sin embargo, extenderlo para manejar múltiples expresiones no es difícil.