Julia Language
String Macro's
Zoeken…
Syntaxis
- macro "string" # kort, string macro vorm
- @macro_str "string" # lange, regelmatige macrovorm
- macro`command`
Opmerkingen
Tekenreeksmacro's zijn niet zo krachtig als gewone oude tekenreeksen - omdat interpolatie moet worden geïmplementeerd in de logica van de macro, kunnen tekenreeksmacro's geen tekenreeksliteralen van hetzelfde scheidingsteken bevatten voor interpolatie.
Bijvoorbeeld, hoewel
julia> "$("x")"
"x"
werkt, de string macrotekstvorm
julia> doc"$("x")"
ERROR: KeyError: key :x not found
wordt onjuist ontleed. Dit kan enigszins worden beperkt door drievoudige aanhalingstekens te gebruiken als het scheidingsteken voor de buitenste tekenreeks;
julia> doc"""$("x")"""
"x"
werkt inderdaad naar behoren.
Stringmacro's gebruiken
Stringmacro's zijn syntactische suiker voor bepaalde macro-aanroepen. De parser vergroot de syntaxis zoals
mymacro"my string"
in
@mymacro_str "my string"
die dan, net als elke andere macro-aanroep, wordt vervangen door elke expressie die de macro @mymacro_str
retourneert. Base Julia wordt geleverd met verschillende tekenreeksmacro's, zoals:
@b_str
Deze tekenreeksmacro construeert byte- arrays in plaats van tekenreeksen . De inhoud van de tekenreeks, gecodeerd als UTF-8, wordt gebruikt als de reeks bytes. Dit kan handig zijn voor de koppeling met low-level API's, waarvan vele werken met byte-arrays in plaats van tekenreeksen.
julia> b"Hello World!"
12-element Array{UInt8,1}:
0x48
0x65
0x6c
0x6c
0x6f
0x20
0x57
0x6f
0x72
0x6c
0x64
0x21
@big_str
Deze macro retourneert een BigInt
of een BigFloat
ontleend aan de gegeven string.
julia> big"1"
1
julia> big"1.0"
1.000000000000000000000000000000000000000000000000000000000000000000000000000000
Deze macro bestaat omdat big(0.1)
zich niet gedraagt zoals je in eerste instantie zou verwachten: de 0.1
is een Float64
benadering van echte 0.1
( 1//10
) en het promoten van dat naar BigFloat
zal de benaderingsfout van Float64
. Het gebruik van de macro zal 0.1
rechtstreeks naar een BigFloat
, waardoor de benaderingsfout wordt verminderd.
julia> big(0.1)
1.000000000000000055511151231257827021181583404541015625000000000000000000000000e-01
julia> big"0.1"
1.000000000000000000000000000000000000000000000000000000000000000000000000000002e-01
@doc_str
Deze tekenreeksmacro construeert Base.Markdown.MD
objecten, die in het interne documentatiesysteem worden gebruikt om rich- Base.Markdown.MD
voor elke omgeving te bieden. Deze MD-objecten worden goed weergegeven in een terminal:
en ook in een browser:
@html_str
Deze tekenreeksmacro construeert HTML-tekenreeksliteralen, die mooi worden weergegeven in een browser:
@ip_str
Deze tekenreeksmacro construeert IP-adresliteralen. Het werkt met zowel IPv4 als IPv6:
julia> ip"127.0.0.1"
ip"127.0.0.1"
julia> ip"::"
ip"::"
@r_str
Deze tekenreeksmacro construeert Regex
literalen .
@s_str
Deze tekenreeksmacro construeert SubstitutionString
literals, die samenwerken met Regex
literals om meer geavanceerde tekstuele substitutie mogelijk te maken.
@text_str
Deze tekenreeksmacro is qua geest vergelijkbaar met @doc_str
en @html_str
, maar heeft geen fancy opmaakfuncties:
@v_str
Deze tekenreeksmacro construeert VersionNumber
literalen. Zie Versienummers voor een beschrijving van wat ze zijn en hoe ze te gebruiken.
@MIME_str
Deze tekenreeksmacro construeert de singleton-typen MIME-typen. MIME"text/plain"
is bijvoorbeeld het type MIME("text/plain")
.
Symbolen die geen wettelijke identificatie zijn
Julia Symbol-literalen moeten wettelijke identificatiegegevens zijn. Dit werkt:
julia> :cat
:cat
Maar dit betekent niet:
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
...
Wat hier als een letterlijke symbool lijkt, wordt eigenlijk ontleed als een impliciete vermenigvuldiging van :2
(wat slechts 2
) en de functie cat
, die duidelijk niet werkt.
We kunnen gebruiken
julia> Symbol("2cat")
Symbol("2cat")
om het probleem te omzeilen.
Een tekenreeksmacro kan helpen om dit korter te maken. Als we de macro @sym_str
definiëren:
macro sym_str(str)
Meta.quot(Symbol(str))
end
dan kunnen we het gewoon doen
julia> sym"2cat"
Symbol("2cat")
om symbolen te maken die geen geldige Julia-ID's zijn.
Natuurlijk kunnen deze technieken ook symbolen die geldig Julia identifiers te creëren. Bijvoorbeeld,
julia> sym"test"
:test
Interpolatie implementeren in een tekenreeksmacro
Stringmacro's worden niet geleverd met ingebouwde interpolatiefaciliteiten . Het is echter mogelijk om deze functionaliteit handmatig te implementeren. Merk op dat het niet mogelijk is om in te sluiten zonder te ontsnappen aan stringliterals die hetzelfde scheidingsteken hebben als de omringende stringmacro; dat wil zeggen, hoewel """ $("x") """
mogelijk is, " $("x") "
niet. In plaats daarvan moet dit worden ontsnapt als " $(\"x\") "
. Zie het opmerkingengedeelte voor meer informatie over deze beperking.
Er zijn twee benaderingen voor het handmatig implementeren van interpolatie: implementeer parsing handmatig of laat Julia de parsering uitvoeren. De eerste benadering is flexibeler, maar de tweede benadering is eenvoudiger.
Handmatig parseren
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 ontleden
macro e_str(s)
esc(parse("\"$(escape_string(s))\""))
end
Deze methode ontsnapt aan de string (maar escape_string
er rekening mee dat escape_string
niet aan de $
-tekens ontsnapt) en geeft deze terug aan de parser van Julia om te parseren. Ontsnappen aan de string is noodzakelijk om ervoor te zorgen dat "
en \
geen invloed hebben op het parseren van de string. De resulterende expressie is een :string
uitdrukking, die kan worden onderzocht en ontleed voor macro-doeleinden.
Opdrachtmacro's
In Julia v0.6 en hoger worden opdrachtmacro's ondersteund naast reguliere tekenreeksmacro's. Een opdracht macro-aanroep zoals
mymacro`xyz`
wordt ontleed als de macro-aanroep
@mymacro_cmd "xyz"
Merk op dat dit vergelijkbaar is met tekenreeksmacro's, behalve met _cmd
plaats van _str
.
Wij gebruiken meestal de opdracht macro's voor code, die in vele talen bevat vaak "
maar zelden bevat `
Zo is het vrij eenvoudig om een eenvoudige versie van herimplementeren. Quasiquoting behulp van command-macro's:
macro julia_cmd(s)
esc(Meta.quot(parse(s)))
end
We kunnen deze macro inline gebruiken:
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)
of multiline:
julia> julia```
function hello()
println("Hello, World!")
end
```
:(function hello() # none, line 2:
println("Hello, World!")
end)
Interpolatie met $
wordt ondersteund:
julia> x = 2
2
julia> julia`1 + $x`
:(1 + 2)
maar de hier gegeven versie staat slechts één expressie toe:
julia> julia```
x = 2
y = 3
```
ERROR: ParseError("extra token after end of expression")
Het is echter niet moeilijk om het uit te breiden om meerdere expressies aan te kunnen.