Julia Language
Macro di stringa
Ricerca…
Sintassi
- macro "stringa" # breve, forma macro di stringa
- @macro_str "stringa" # lungo, normale modulo macro
- macro`command`
Osservazioni
Le macro di stringa non sono altrettanto potenti delle semplici stringhe vecchie: poiché l'interpolazione deve essere implementata nella logica della macro, le macro di stringa non sono in grado di contenere valori letterali di stringa dello stesso delimitatore per l'interpolazione.
Ad esempio, anche se
julia> "$("x")"
"x"
funziona, la forma del testo macro della stringa
julia> doc"$("x")"
ERROR: KeyError: key :x not found
viene analizzato in modo errato. Questo può essere in qualche modo mitigato usando le virgolette triple come delimitatore di stringhe esterne;
julia> doc"""$("x")"""
"x"
funziona davvero correttamente.
Utilizzo di macro di stringa
Le macro di stringa sono zucchero sintattico per alcune invocazioni di macro. Il parser espande la sintassi come
mymacro"my string"
in
@mymacro_str "my string"
che poi, come qualsiasi altra macro chiamata, viene sostituita con qualsiasi espressione @mymacro_str
macro @mymacro_str
. Base Julia viene fornito con diverse macro di stringa, come ad esempio:
@b_str
Questa macro di stringhe costruisce array di byte invece di stringhe . Il contenuto della stringa, codificato come UTF-8, verrà utilizzato come matrice di byte. Questo può essere utile per l'interfacciamento con API di basso livello, molte delle quali funzionano con array di byte invece di stringhe.
julia> b"Hello World!"
12-element Array{UInt8,1}:
0x48
0x65
0x6c
0x6c
0x6f
0x20
0x57
0x6f
0x72
0x6c
0x64
0x21
@big_str
Questa macro restituirà un BigInt
o un BigFloat
analizzato dalla stringa fornita.
julia> big"1"
1
julia> big"1.0"
1.000000000000000000000000000000000000000000000000000000000000000000000000000000
Questa macro esiste perché big(0.1)
non si comporta come ci si aspetterebbe inizialmente: lo 0.1
è un'approssimazione Float64
di true 0.1
( 1//10
), e promuoverlo a BigFloat
manterrà l'errore di approssimazione di Float64
. L'uso della macro analizzerà 0.1
direttamente su un BigFloat
, riducendo l'errore di approssimazione.
julia> big(0.1)
1.000000000000000055511151231257827021181583404541015625000000000000000000000000e-01
julia> big"0.1"
1.000000000000000000000000000000000000000000000000000000000000000000000000000002e-01
@doc_str
Questa macro di stringhe costruisce oggetti Base.Markdown.MD
, che vengono utilizzati nel sistema di documentazione interno per fornire documentazione di testo completo per qualsiasi ambiente. Questi oggetti MD rendono bene in un terminale:
e anche in un browser:
@html_str
Questa macro di stringhe costruisce letterali stringa HTML, che rendono bene in un browser:
@ip_str
Questa macro di stringhe costruisce letterali di indirizzo IP. Funziona con IPv4 e IPv6:
julia> ip"127.0.0.1"
ip"127.0.0.1"
julia> ip"::"
ip"::"
@r_str
Questa macro di stringhe costruisce i valori letterali di Regex
.
@s_str
Questa macro di stringhe costruisce letterali di SubstitutionString
, che Regex
con i letterali di Regex
per consentire una sostituzione testuale più avanzata.
@text_str
Questa macro di stringa è simile nello spirito a @doc_str
e @html_str
, ma non ha alcuna caratteristica di formattazione:
@v_str
Questa macro di stringhe costruisce valori letterali VersionNumber
. Vedi i numeri di versione per una descrizione di cosa sono e come usarli.
@MIME_str
Questa macro di stringhe costruisce i tipi singleton di tipi MIME. Ad esempio, MIME"text/plain"
è il tipo di MIME("text/plain")
.
Simboli che non sono identificativi legali
I valori letterali del simbolo di Julia devono essere identificativi legali. Questo funziona:
julia> :cat
:cat
Ma questo non:
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
...
Ciò che sembra un letterale di simboli qui viene in realtà analizzato come una moltiplicazione implicita di :2
(che è solo 2
) e la funzione cat
, che ovviamente non funziona.
Possiamo usare
julia> Symbol("2cat")
Symbol("2cat")
per aggirare il problema.
Una macro di stringhe potrebbe aiutare a renderlo più conciso. Se definiamo la macro @sym_str
:
macro sym_str(str)
Meta.quot(Symbol(str))
end
allora possiamo semplicemente fare
julia> sym"2cat"
Symbol("2cat")
per creare simboli che non sono identificativi di Julia validi.
Naturalmente, queste tecniche possono anche creare simboli che sono identificativi di Julia validi. Per esempio,
julia> sym"test"
:test
Implementazione dell'interpolazione in una macro di stringhe
Le macro di stringa non vengono fornite con le funzioni di interpolazione incorporate. Tuttavia, è possibile implementare manualmente questa funzionalità. Si noti che non è possibile incorporare senza eseguire l'escape di stringhe letterali che hanno lo stesso delimitatore della macro di stringa circostante; vale a dire, sebbene """ $("x") """
sia possibile, " $("x") "
non lo è. Invece, questo deve essere salvato come " $(\"x\") "
. Vedere la sezione commenti per maggiori dettagli su questa limitazione.
Esistono due approcci per implementare l'interpolazione manualmente: implementare l'analisi manualmente o fare in modo che Julia esegua l'analisi. Il primo approccio è più flessibile, ma il secondo approccio è più semplice.
Analisi manuale
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 analizza
macro e_str(s)
esc(parse("\"$(escape_string(s))\""))
end
Questo metodo sfugge alla stringa (ma nota che escape_string
non sfugge ai $
sign) e lo restituisce al parser di Julia per analizzarlo. L'escape della stringa è necessario per garantire che "
e \
non influenzino l'analisi della stringa. L'espressione risultante è un'espressione :string
, che può essere esaminata e scomposta per scopi macro.
Macro di comando
In Julia v0.6 e successive, le macro di comando sono supportate in aggiunta alle normali macro di stringa. Un richiamo di macro di comando come
mymacro`xyz`
viene analizzato come la chiamata macro
@mymacro_cmd "xyz"
Si noti che questo è simile alle macro di stringa, tranne con _cmd
invece di _str
.
Normalmente usiamo macro di comandi per il codice, che in molte lingue spesso contiene "
ma raramente contiene `
. Ad esempio, è abbastanza semplice reimplementare una versione semplice di quasiquoting usando le macro di comando:
macro julia_cmd(s)
esc(Meta.quot(parse(s)))
end
Possiamo usare questa macro sia in linea:
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 multilinea:
julia> julia```
function hello()
println("Hello, World!")
end
```
:(function hello() # none, line 2:
println("Hello, World!")
end)
L'interpolazione usando $
è supportata:
julia> x = 2
2
julia> julia`1 + $x`
:(1 + 2)
ma la versione qui fornita consente solo un'espressione:
julia> julia```
x = 2
y = 3
```
ERROR: ParseError("extra token after end of expression")
Tuttavia, estenderlo per gestire più espressioni non è difficile.