Julia Language
Makra ciągów
Szukaj…
Składnia
- makro „string” # krótki, forma makra string
- @macro_str "string" # długi, regularny formularz makra
- makro`command`
Uwagi
Makra łańcuchowe nie są tak potężne jak zwykłe stare łańcuchy - ponieważ interpolacja musi być zaimplementowana w logice makra, makra łańcuchowe nie mogą zawierać literałów łańcuchowych tego samego separatora do interpolacji.
Na przykład chociaż
julia> "$("x")"
"x"
działa, formularz tekstowy makro ciąg
julia> doc"$("x")"
ERROR: KeyError: key :x not found
jest nieprawidłowo analizowany. Można to nieco złagodzić, używając potrójnych cudzysłowów jako zewnętrznego ogranicznika łańcucha;
julia> doc"""$("x")"""
"x"
naprawdę działa poprawnie.
Używanie makr łańcuchowych
Makra łańcuchowe są cukrem syntaktycznym dla niektórych wywołań makr. Analizator składni rozszerza składnię jak
mymacro"my string"
w
@mymacro_str "my string"
który następnie, jak każde inne wywołanie makra, zostaje zastąpiony dowolnym wyrażeniem @mymacro_str
makro @mymacro_str
. Baza Julia zawiera kilka makr łańcuchowych, takich jak:
@b_str
To makro ciągów konstruuje tablice bajtów zamiast ciągów . Zawartość łańcucha, zakodowanego jako UTF-8, będzie używana jako tablica bajtów. Może to być przydatne w przypadku interfejsów API niskiego poziomu, z których wiele działa z tablicami bajtów zamiast ciągów.
julia> b"Hello World!"
12-element Array{UInt8,1}:
0x48
0x65
0x6c
0x6c
0x6f
0x20
0x57
0x6f
0x72
0x6c
0x64
0x21
@big_str
To makro zwróci BigInt
lub BigFloat
parsowane z podanego ciągu.
julia> big"1"
1
julia> big"1.0"
1.000000000000000000000000000000000000000000000000000000000000000000000000000000
To makro istnieje, ponieważ big(0.1)
nie zachowuje się tak, jak można się początkowo spodziewać: 0.1
jest przybliżeniem Float64
wartości 0.1
( 1//10
), a promowanie go do BigFloat
spowoduje zachowanie błędu przybliżenia Float64
. Użycie makra BigFloat
0.1
bezpośrednio do BigFloat
, zmniejszając błąd aproksymacji.
julia> big(0.1)
1.000000000000000055511151231257827021181583404541015625000000000000000000000000e-01
julia> big"0.1"
1.000000000000000000000000000000000000000000000000000000000000000000000000000002e-01
@doc_str
To makro ciągów konstruuje obiekty Base.Markdown.MD
, które są używane w wewnętrznym systemie dokumentacji do dostarczania dokumentacji tekstowej dla dowolnego środowiska. Te obiekty MD dobrze renderują się w terminalu:
a także w przeglądarce:
@html_str
To makro ciągów tworzy literały ciągów HTML, które ładnie renderują się w przeglądarce:
@ip_str
To makro ciągu konstruuje literały adresu IP. Działa zarówno z IPv4, jak i IPv6:
julia> ip"127.0.0.1"
ip"127.0.0.1"
julia> ip"::"
ip"::"
@r_str
To makro łańcuchowe tworzy literały Regex
.
@s_str
To makro łańcuchowe konstruuje literały SubstitutionString
, które współpracują z literałami Regex
aby umożliwić bardziej zaawansowane podstawianie tekstu.
@text_str
To makro ciągu jest podobne w duchu do @doc_str
i @html_str
, ale nie ma żadnych fantazyjnych funkcji formatowania:
@v_str
To makro ciągu konstruuje literały VersionNumber
. Zobacz Numery wersji, aby uzyskać opis tego, czym są i jak z nich korzystać.
@MIME_str
To makro łańcuchowe konstruuje typy singletonów typów MIME. Na przykład MIME"text/plain"
jest typem MIME("text/plain")
.
Symbole, które nie są prawnymi identyfikatorami
Literały Julia Symbol muszą być prawnymi identyfikatorami. To działa:
julia> :cat
:cat
Ale to nie:
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
...
To, co wygląda tutaj na dosłowny symbol, jest w rzeczywistości analizowane jako ukryte mnożenie :2
(czyli tylko 2
) i funkcji cat
, która oczywiście nie działa.
Możemy użyć
julia> Symbol("2cat")
Symbol("2cat")
obejść ten problem.
Makro ciągu może pomóc uczynić to bardziej zwięzłym. Jeśli zdefiniujemy makro @sym_str
:
macro sym_str(str)
Meta.quot(Symbol(str))
end
wtedy możemy po prostu zrobić
julia> sym"2cat"
Symbol("2cat")
do tworzenia symboli, które nie są prawidłowymi identyfikatorami Julii.
Oczywiście techniki te mogą również tworzyć symbole, które są ważnymi identyfikatorami Julii. Na przykład,
julia> sym"test"
:test
Implementowanie interpolacji w makrze ciągów
Makra łańcuchowe nie są dostarczane z wbudowanymi funkcjami interpolacji . Możliwe jest jednak ręczne wdrożenie tej funkcji. Zauważ, że nie jest możliwe osadzanie bez znaków literowych łańcucha, które mają ten sam separator, co otaczające makro łańcucha; to znaczy, chociaż """ $("x") """
jest możliwe, " $("x") "
nie jest możliwe. Zamiast tego musi być poprzedzony znakiem " $(\"x\") "
. Więcej informacji na temat tego ograniczenia znajduje się w sekcji uwag .
Istnieją dwa podejścia do ręcznej implementacji interpolacji: ręczne analizowanie składni lub zlecenie Julii wykonania analizy. Pierwsze podejście jest bardziej elastyczne, ale drugie podejście jest łatwiejsze.
Parsowanie ręczne
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 analizuje
macro e_str(s)
esc(parse("\"$(escape_string(s))\""))
end
Ta metoda unika ciągu znaków (ale należy pamiętać, że escape_string
nie ucieka znakom $
) i przekazuje go z powrotem do analizatora składni Julii w celu przetworzenia. Ucieczka łańcucha jest niezbędna, aby upewnić się, że "
i \
nie wpływają na parsowanie łańcucha. Wynikiem tego jest wyrażenie :string
, które można badać i rozkładać w celach makro.
Makra poleceń
W Julii v0.6 i nowszych makra poleceń są obsługiwane oprócz zwykłych makr łańcuchowych. Wywołanie makra polecenia jak
mymacro`xyz`
jest analizowany jako wywołanie makra
@mymacro_cmd "xyz"
Zauważ, że jest to podobne do makr łańcuchowych, z wyjątkiem _cmd
zamiast _str
.
Zwykle używamy makr poleceń do kodu, który w wielu językach często zawiera "
ale rzadko zawiera `
. Na przykład dość łatwo jest zaimplementować prostą wersję quasi-cytowania za pomocą makr poleceń:
macro julia_cmd(s)
esc(Meta.quot(parse(s)))
end
Możemy użyć tego makra albo bezpośrednio:
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)
lub multilinii:
julia> julia```
function hello()
println("Hello, World!")
end
```
:(function hello() # none, line 2:
println("Hello, World!")
end)
Obsługiwana jest interpolacja za pomocą $
:
julia> x = 2
2
julia> julia`1 + $x`
:(1 + 2)
ale podana tutaj wersja dopuszcza tylko jedno wyrażenie:
julia> julia```
x = 2
y = 3
```
ERROR: ParseError("extra token after end of expression")
Jednak rozszerzenie go na obsługę wielu wyrażeń nie jest trudne.