Julia Language
Wyrażenia
Szukaj…
Wprowadzenie do wyrażeń
Wyrażenia są specyficznym typem obiektu w Julii. Możesz myśleć o wyrażeniu, które reprezentuje fragment kodu Julii, który nie został jeszcze oceniony (tzn. Wykonany). Istnieją wtedy określone funkcje i operacje, takie jak eval()
które będą oceniać wyrażenie.
Na przykład możemy napisać skrypt lub wprowadzić do interpretera następujące polecenia: julia> 1 + 1 2
Jednym ze sposobów utworzenia wyrażenia jest użycie składni :()
. Na przykład:
julia> MyExpression = :(1+1)
:(1 + 1)
julia> typeof(MyExpression)
Expr
Mamy teraz obiekt typu Expr
. Właśnie powstały, nic nie robi - po prostu siedzi wokół, jak każdy inny przedmiot, dopóki nie zostanie na nie uruchomiony. W takim przypadku możemy ocenić to wyrażenie za pomocą funkcji eval()
:
julia> eval(MyExpression)
2
Widzimy zatem, że następujące dwa są równoważne:
1+1
eval(:(1+1))
Dlaczego chcielibyśmy przejść przez znacznie bardziej skomplikowaną składnię w eval(:(1+1))
jeśli chcemy po prostu znaleźć, co równa się 1 + 1? Podstawowym powodem jest to, że możemy zdefiniować wyrażenie w jednym punkcie naszego kodu, potencjalnie zmodyfikować je później, a następnie ocenić w późniejszym momencie. Może to potencjalnie otworzyć potężne nowe możliwości dla programisty Julii. Wyrażenia są kluczowym elementem metaprogramowania w Julii.
Tworzenie wyrażeń
Istnieje wiele różnych metod, których można użyć do stworzenia tego samego typu wyrażenia. Wprowadzenie do wyrażeń wspomniało o składni :()
. Być może najlepszym miejscem na początek są jednak łańcuchy. Pomaga to ujawnić niektóre podstawowe podobieństwa między wyrażeniami i łańcuchami w Julii.
Utwórz wyrażenie na podstawie ciągu
Z dokumentacji Julii:
Każdy program Julii zaczyna życie jako ciąg
Innymi słowy, każdy skrypt Julii jest po prostu zapisany w pliku tekstowym, który jest niczym innym jak ciągiem znaków. Podobnie każde polecenie Julii wprowadzone do interpretera jest tylko ciągiem znaków. Rolą Julii lub innego języka programowania jest zatem interpretacja i ocena ciągów znaków w logiczny, przewidywalny sposób, dzięki czemu te ciągi znaków można wykorzystać do opisania tego, co programista chce osiągnąć na komputerze.
Dlatego jednym ze sposobów utworzenia wyrażenia jest użycie funkcji parse()
zastosowanej do łańcucha. Poniższe wyrażenie, po jego ocenie, przypisze wartość 2 do symbolu x
.
MyStr = "x = 2"
MyExpr = parse(MyStr)
julia> x
ERROR: UndefVarError: x not defined
eval(MyExpr)
julia> x
2
Utwórz wyrażenie za pomocą :()
Składnia
MyExpr2 = :(x = 2)
julia> MyExpr == MyExpr2
true
Zauważ, że dzięki tej składni Julia automatycznie będzie traktować nazwy obiektów jako odnoszące się do symboli. Możemy to zobaczyć, jeśli spojrzymy na args
wyrażenia. (Zobacz Fields of Expression Objects, aby uzyskać więcej informacji na temat pola args
w wyrażeniu.)
julia> MyExpr2.args
2-element Array{Any,1}:
:x
2
Utwórz wyrażenie za pomocą funkcji Expr()
MyExpr3 = Expr(:(=), :x, 2)
MyExpr3 == MyExpr
Ta składnia oparta jest na notacji przedrostków . Innymi słowy, pierwszym argumentem określonej funkcji Expr()
jest head
lub przedrostek. Pozostałe to arguments
wyrażenia. head
określa, jakie operacje będą wykonywane na argumentach.
Aby uzyskać więcej informacji na ten temat, zobacz Fields of Expression Objects
Podczas korzystania z tej składni ważne jest rozróżnienie między używaniem obiektów i symboli dla obiektów. Na przykład w powyższym przykładzie wyrażenie przypisuje wartość 2
do symbolu :x
, operacja całkowicie sensowna. Gdybyśmy użyli samego x
w takim wyrażeniu, otrzymalibyśmy nonsensowny wynik:
julia> Expr(:(=), x, 5)
:(2 = 5)
Podobnie, jeśli zbadamy args
, zobaczymy:
julia> Expr(:(=), x, 5).args
2-element Array{Any,1}:
2
5
Dlatego funkcja Expr()
nie wykonuje takiej samej automatycznej transformacji w symbole jak składnia :()
do tworzenia wyrażeń.
Twórz wyrażenia wieloliniowe, używając quote...end
MyQuote =
quote
x = 2
y = 3
end
julia> typeof(MyQuote)
Expr
Zauważ, że za pomocą quote...end
możemy tworzyć wyrażenia, które zawierają inne wyrażenia w polu args
:
julia> typeof(MyQuote.args[2])
Expr
Zobacz Fields of Expression Objects, aby uzyskać więcej informacji na temat tego pola args
.
Więcej informacji o tworzeniu wyrażeń
W tym przykładzie podano jedynie podstawy tworzenia wyrażeń. Zobacz także na przykład Interpolacja i Obiekty wyrażeń i Pola wyrażeń, aby uzyskać więcej informacji na temat tworzenia bardziej złożonych i zaawansowanych wyrażeń.
Pola ekspresji obiektów
Jak wspomniano we wprowadzeniu do wyrażeń, wyrażenia są szczególnym typem obiektu w Julii. Jako takie mają pola. Dwa najczęściej używane pola wyrażenia to jego head
i args
. Rozważmy na przykład wyrażenie
MyExpr3 = Expr(:(=), :x, 2)
omówione w Creating Expressions . Możemy zobaczyć head
i args
w następujący sposób:
julia> MyExpr3.head
:(=)
julia> MyExpr3.args
2-element Array{Any,1}:
:x
2
Wyrażenia oparte są na zapisie prefiksu . Jako taki, head
ogólnie określa operację, która ma być wykonana na args
. Głowa musi być Symbol
typu Julia.
Gdy wyrażenie ma przypisać wartość (kiedy jest oceniane), zwykle używa nagłówka :(=)
. Istnieją oczywiście oczywiste różnice, które można zastosować, np .:
ex1 = Expr(:(+=), :x, 2)
: wezwij głowy ekspresji
Innym częstym head
do wyrażenia to :call
. Na przykład
ex2 = Expr(:call, :(*), 2, 3)
eval(ex2) ## 6
Zgodnie z konwencją notacji przedrostków operatory są oceniane od lewej do prawej. Wyrażenie to oznacza tutaj, że wywołamy funkcję określoną w pierwszym elemencie args
w kolejnych elementach. Podobnie moglibyśmy:
julia> ex2a = Expr(:call, :(-), 1, 2, 3)
:(1 - 2 - 3)
Lub inne, potencjalnie bardziej interesujące funkcje, np
julia> ex2b = Expr(:call, :rand, 2,2)
:(rand(2,2))
julia> eval(ex2b)
2x2 Array{Float64,2}:
0.429397 0.164478
0.104994 0.675745
Automatyczne określanie head
przy użyciu notacji tworzenia wyrażeń :()
Zauważ, że :call
jest domyślnie używane jako głowa w niektórych konstrukcjach wyrażeń, np
julia> :(x + 2).head
:call
W związku z tym dzięki składni :()
do tworzenia wyrażeń Julia będzie starała się automatycznie określić prawidłową głowicę do użycia. Podobnie:
julia> :(x = 2).head
:(=)
W rzeczywistości, jeśli nie masz pewności, jakiej właściwej głowy użyć do wyrażenia, które tworzysz, na przykład Expr()
może to być pomocne narzędzie, aby uzyskać wskazówki i pomysły na temat tego, czego użyć.
Interpolacja i wyrażenia
Tworzenie wyrażeń wspomina, że wyrażenia są ściśle powiązane z łańcuchami. Jako takie, zasady interpolacji w łańcuchach są również istotne dla wyrażeń. Na przykład w podstawowej interpolacji ciągów możemy uzyskać coś takiego:
n = 2
julia> MyString = "there are $n ducks"
"there are 2 ducks"
Używamy znaku $
aby wstawić wartość n
do ciągu. Możemy używać tej samej techniki z wyrażeniami. Na przykład
a = 2
ex1 = :(x = 2*$a) ## :(x = 2 * 2)
a = 3
eval(ex1)
x # 4
Porównaj to w ten sposób:
a = 2
ex2 = :(x = 2*a) # :(x = 2a)
a = 3
eval(ex2)
x # 6
Tak więc, w pierwszym przykładzie, z góry ustalamy wartość a
która będzie używana w czasie oceny wyrażenia. Z drugim przykładzie, jednak kompilator Julia będzie wyglądać tylko znaleźć swoją wartość w momencie oceny dla naszej wypowiedzi. a
Odnośniki zewnętrzne dotyczące wyrażeń
Istnieje wiele przydatnych zasobów internetowych, które mogą pomóc w pogłębieniu wiedzy o wyrażeniach w Julii. Obejmują one:
- Julia Docs - Metaprogramowanie
- Wikibooks - Julia Metaprogramming
- Makra, wyrażenia itp. Julii dla i przez zdezorientowanych, Grey Calhoun
- Miesiąc Julii - Metaprogramowanie, autor: Andrew Collier
- Symboliczne różnicowanie w Julii, autor: John Myles White
Posty SO:
- Co to jest „symbol” u Julii? Odpowiedź Stefana Karpińskiego
- Dlaczego Julia wyraża to wyrażenie w tak złożony sposób?
- Wyjaśnienie przykładu interpolacji wyrażeń Julii