Julia Language
Macros de chaîne
Recherche…
Syntaxe
- macro "string" # short, chaîne de forme de macro
- @macro_str "string" # forme de macro longue et régulière
- macro`command`
Remarques
Les macros de chaînes de caractères ne sont pas aussi puissantes que les anciennes chaînes de caractères ordinaires - car l'interpolation doit être implémentée dans la logique de la macro, les macros de chaînes ne peuvent pas contenir de littéraux de chaîne du même délimiteur pour l'interpolation.
Par exemple, bien que
julia> "$("x")"
"x"
fonctionne, la forme de texte de macro de chaîne
julia> doc"$("x")"
ERROR: KeyError: key :x not found
est analysé de manière incorrecte. Cela peut être quelque peu atténué en utilisant des guillemets comme séparateur de chaîne externe;
julia> doc"""$("x")"""
"x"
fonctionne effectivement correctement.
Utiliser des macros de chaîne
Les macros de chaîne sont du sucre syntaxique pour certaines invocations de macros. L'analyseur développe la syntaxe comme
mymacro"my string"
dans
@mymacro_str "my string"
qui, comme tout autre appel de macro, est remplacé par l'expression que @mymacro_str
macro @mymacro_str
. La base Julia est fournie avec plusieurs macros de chaîne, telles que:
@b_str
Cette macro de chaîne construit des tableaux d' octets au lieu de chaînes . Le contenu de la chaîne, codé en UTF-8, sera utilisé comme tableau d'octets. Cela peut être utile pour l'interfaçage avec des API de bas niveau, dont beaucoup fonctionnent avec des tableaux d'octets au lieu de chaînes.
julia> b"Hello World!"
12-element Array{UInt8,1}:
0x48
0x65
0x6c
0x6c
0x6f
0x20
0x57
0x6f
0x72
0x6c
0x64
0x21
@big_str
Cette macro renvoie un BigInt
ou un BigFloat
analysé à partir de la chaîne fournie.
julia> big"1"
1
julia> big"1.0"
1.000000000000000000000000000000000000000000000000000000000000000000000000000000
Cette macro existe car big(0.1)
ne se comporte pas comme on pouvait s’y attendre: le 0.1
est une approximation Float64
de true 0.1
( 1//10
), et la promotion de cette BigFloat
à BigFloat
conservera l’erreur d’approximation de Float64
. Utiliser la macro analysera 0.1
directement dans un BigFloat
, réduisant ainsi l’erreur d’approximation.
julia> big(0.1)
1.000000000000000055511151231257827021181583404541015625000000000000000000000000e-01
julia> big"0.1"
1.000000000000000000000000000000000000000000000000000000000000000000000000000002e-01
@doc_str
Cette macro de chaîne Base.Markdown.MD
objets Base.Markdown.MD
, qui sont utilisés dans le système de documentation interne pour fournir une documentation en texte riche pour tout environnement. Ces objets MD se rendent bien dans un terminal:
et aussi dans un navigateur:
@html_str
Cette macro de chaîne construit des littéraux de chaîne HTML, qui s'affichent bien dans un navigateur:
@ip_str
Cette macro de chaîne construit des littéraux d'adresse IP. Il fonctionne avec IPv4 et IPv6:
julia> ip"127.0.0.1"
ip"127.0.0.1"
julia> ip"::"
ip"::"
@r_str
Cette macro de chaîne construit des littéraux Regex
.
@s_str
Cette macro de chaîne construit des littéraux SubstitutionString
, qui fonctionnent avec les littéraux Regex
pour permettre une substitution textuelle plus avancée.
@text_str
Cette macro de chaîne est similaire dans l'esprit à @doc_str
et @html_str
, mais ne possède aucune fonctionnalité de formatage sophistiquée:
@v_str
Cette macro de chaîne construit des littéraux VersionNumber
. Voir les numéros de version pour une description de ce qu'ils sont et comment les utiliser.
@MIME_str
Cette macro de chaîne construit les types singleton des types MIME. Par exemple, MIME"text/plain"
est le type de MIME("text/plain")
.
Symboles qui ne sont pas des identifiants légaux
Les symboles littéraux de Julia doivent être des identificateurs légaux. Cela marche:
julia> :cat
:cat
Mais cela ne fait pas:
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
...
Ce qui ressemble à un littéral de symbole ici est en fait analysé comme une multiplication implicite de :2
(qui est juste 2
) et la fonction cat
, qui ne fonctionne évidemment pas.
On peut utiliser
julia> Symbol("2cat")
Symbol("2cat")
pour contourner le problème.
Une macro de chaîne pourrait aider à rendre ceci plus concis. Si nous définissons la macro @sym_str
:
macro sym_str(str)
Meta.quot(Symbol(str))
end
alors on peut simplement faire
julia> sym"2cat"
Symbol("2cat")
pour créer des symboles qui ne sont pas des identifiants Julia valides.
Bien entendu, ces techniques peuvent également créer des symboles qui sont des identifiants Julia valides. Par exemple,
julia> sym"test"
:test
Implémentation de l'interpolation dans une macro de chaîne
Les macros de chaîne ne sont pas fournies avec des fonctions d' interpolation intégrées. Cependant, il est possible d'implémenter manuellement cette fonctionnalité. Notez qu'il n'est pas possible d'incorporer sans échapper les littéraux de chaîne qui ont le même délimiteur que la macro de chaîne environnante; c'est-à-dire que """ $("x") """
est possible, " $("x") "
n'est pas. Au lieu de cela, cela doit être échappé comme " $(\"x\") "
. Voir la section des remarques pour plus de détails sur cette limitation.
Il existe deux approches pour implémenter l'interpolation manuellement: implémenter l'analyse syntaxique manuellement ou demander à Julia d'effectuer l'analyse. La première approche est plus flexible, mais la seconde approche est plus facile.
Analyse manuelle
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 analyse
macro e_str(s)
esc(parse("\"$(escape_string(s))\""))
end
Cette méthode échappe à la chaîne (mais notez que la escape_string
n'échappe pas aux signes $
) et la renvoie à l'analyseur syntaxique de Julia pour l'analyse. Echapper à la chaîne est nécessaire pour s'assurer que "
et \
n'affecte pas l'analyse de la chaîne. L'expression résultante est une expression :string
, qui peut être examinée et décomposée à des fins macro.
Macros de commande
Dans Julia v0.6 et versions ultérieures, les macros de commandes sont prises en charge en plus des macros de chaîne standard. Une invocation de macro de commande comme
mymacro`xyz`
est analysé comme l'appel de macro
@mymacro_cmd "xyz"
Notez que cela est similaire aux macros de chaînes, sauf avec _cmd
au lieu de _str
.
Nous utilisons généralement des macros de commande pour le code, ce qui dans de nombreuses langues contient souvent "
mais contient rarement `
, par exemple, il est assez facile de ré - écrire une version simple. Quasiquoting en utilisant des macros de commande:
macro julia_cmd(s)
esc(Meta.quot(parse(s)))
end
Nous pouvons utiliser cette macro soit en ligne:
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)
ou multiligne:
julia> julia```
function hello()
println("Hello, World!")
end
```
:(function hello() # none, line 2:
println("Hello, World!")
end)
L'interpolation à l'aide de $
est prise en charge:
julia> x = 2
2
julia> julia`1 + $x`
:(1 + 2)
mais la version donnée ici ne permet qu'une seule expression:
julia> julia```
x = 2
y = 3
```
ERROR: ParseError("extra token after end of expression")
Cependant, l'étendre pour gérer plusieurs expressions n'est pas difficile.