Dlaczego wyrażenia złożone?

10

Oto przykład z książki, którą czytam:

volume = begin
    len = 10
    breadth = 20
    height = 30
    len * breadth * height
end

Dlaczego potrzebuję wyrażeń złożonych? Mógłbym po prostu napisać volume = 10 * 20 * 30lub volume = len * breadth * heightnapisać funkcję dla tej lub anonimowej funkcji ...

Dlaczego używam begini end? Lub prawdopodobnie lepsze pytanie: kiedy ich używam, jak sądzę, powyższy przykład z książki prawdopodobnie nie jest zbyt dobry.

Gruzja
źródło
1
Co to za książka? ponieważ ty też nie jesteś przykładem, nie jest szczególnie dobry
Michael K. Borregaard,
„Nauka Julii”, dostępna tutaj: epdf.pub/learning-julia.html (strona 127)
Georgery

Odpowiedzi:

4

Sądzę, że istnieje wiele sytuacji, w których begin ... endbloki są przydatne, ale jak zauważyłeś, często możesz również osiągnąć podobny efekt z innymi konstrukcjami, takimi jak funkcje itp.

Do czego można begin ... endużyć bloków?

  • Po prostu „zawierają” zmienne i ich nazwy: len, breadth, i heightbędzie istnieć tylko w bloku i nie zanieczyszczają otaczające nazw.
  • Aby zastosować makra do bloku kodu, a nie do pojedynczych instrukcji. Na przykład @inbounds begin <all my code without bounds checking goes here> endlub owijanie @time begin ... endfragmentu kodu.
  • Aby utworzyć zasięg lokalny w otaczającym zasięgu globalnym ( na przykład, aby uniknąć nieporozumień zakresu globalnego ). (Należy zauważyć, że jak wskazano w komentarzach begin ... end, nie wprowadza się zasięgu lokalnego, ale argument dotyczy podobnego let ... endbloku.)

W szczególności drugi punkt dotyczy tego, do czego ich używam w swoich kodach.

crstnbr
źródło
Miałem też uspokoić siebie, ale beginbloki czy nie wprowadzić zakres . Z drugiej strony konwertują sekwencję instrukcji na wyrażenie, co może być przydatne, jeśli generujesz kod za pomocą / z makra.
phipsgabler
1
Och, dzięki, w tym względzie pomyliłem to z let ... endwprowadzeniem zakresu lokalnego. Poprawi moją odpowiedź.
crstnbr
Cały czas robię to samo błędne założenie :) Tego właśnie można się spodziewać.
phipsgabler
1
@crstnbr Twoja pierwsza kula wciąż wprowadza w błąd. Nadal wydaje się, że beginbloki wprowadzają zasięg lokalny.
Cameron Bieganek
7

Aby uogólnić to, co wszyscy inni powiedzieli: bloki pozwalają konwertować listę instrukcji (składniowe „frazy”, które nie mają wartości, tzn. Nie mogą być przypisane) na jedno wyrażenie („fraza”, która reprezentuje wartości i może być przypisana ).

Na przykład, chociaż nie powinieneś, możesz pisać

x = begin
    s = 0
    for i = 1:10
        s += i^2
    end
    s
end

przypisać xdo wyniku operacji zapętlenia. (Z zastrzeżeniem, że ostatnia instrukcja w sekwencji musi faktycznie być wyrażeniem - w przeciwnym razie wyrażenie nie miałoby żadnej wartości).

Uzasadnionym przypadkiem użycia tego jest wygenerowany kod. Na przykład możesz się odwrócić

x = @somthing bla blub

w

x = begin
   (stuff involving bla and blub)
end

w sposób przejrzysty dla użytkownika, podczas gdy @somethingmoże swobodnie generować dowolne konstrukcje językowe.

Lub jeśli chcesz napisać anonimową funkcję o dłuższym ciele (i nie używać functionformularza):

f = x -> begin
   ...
end
phipsgabler
źródło
1
Lekkie wyjaśnienie: w Julii instrukcje mają wartości i można je przypisywać. Możesz więc zrobić x = y = 1, a = if false endi b = for i in 1:2 end, po którym xma wartość 1, ai boba mają wartość nothing.
Cameron Bieganek
Oh, tu jest bardziej użyteczny przykład przypisanie wartości z if-elseoświadczeniem: a = if false; 1 else 2 end. W tym przypadku ajest równy 2.
Cameron Bieganek
1
Racja, mają wartości i są również technicznie wyrażeniami. Przypisanie jest wyrażeniem, ponieważ jest w zasadzie setproperty!/ setindex!i „tradycyjnie” jest rzeczą, która ma wartość (w językach podobnych do C). To samo if-elsedotyczy wyrażenia w kilku językach. Ale fori ifbez elsekonieczności „Domyślna” wartość nothing, widzę, że jedynie jako artefakt.
phipsgabler
6

Jednym z zastosowań tych bloków jest zrozumienie:

A = [ begin
           x = y^2
           x - x^2 + 2
         end
         for y = 1:5 ]

Możesz zrobić funkcję i użyć jej zamiast tego w zrozumieniu, ale czasami jest to wygodne. Jest używany, gdy chcesz gdzieś użyć wielowierszowego bloku kodu, np. Do przekazania jako argumentu do makra (co jest bardzo często używane @testsetw standardowej bibliotece Test).

Eric
źródło
Nie sprzeciwiając się temu, ale można po prostu napisać y^2 - y^4 + 2w tym przypadku. Być może lepiej byłoby pokazać przykład, w którym naprawdę potrzebne są dwa (lub więcej) kroków.
crstnbr
@crstnbr masz rację, ale ja początkowo skorzystałem z przykładu z książki i po prostu byłem zainteresowany, jakie byłoby sensowne użycie.
Georgery
1
Na przykład, aby zaoszczędzić na dwukrotnym obliczeniu drogiej wartości pośredniej.
phipsgabler
5

Mówiąc prosto: „start” oznacza tylko blok kodu (patrz dokumentacja na ten temat: https://docs.julialang.org/en/v1/base/base/#begin ).

W powyższym przykładzie nie jest jasne, czy istnieje jakakolwiek wartość dla użycia bloku początkowego vs. deklarowania funkcji.

Nie widzę tego słowa kluczowego używanego w kodzie i osobiście nigdy go nie używałem w praktyce. Moja sugestia, aby po prostu użyć funkcji, ponieważ zrobi to samo.

logankilpatrick
źródło
Jeszcze nie korzystałem z Julii, ale właśnie o tym myślę. Jednak kiedy język został zaprojektowany (przypuszczalnie bardzo inteligentny), ludzie musieli mieć na myśli jakiś pomysł, prawda?
Georgery
Zgadzam się z @logankilpatrick, że w wielu przypadkach zamiast tego chcesz użyć funkcji. Myślę jednak, że istnieją powody istnienia tych bloków (patrz moja odpowiedź).
crstnbr
@ Georgia Przekształcanie sekwencji wyrażeń w wyrażenie jest czasem przydatne (por. prognW LISP).
phipsgabler
1
jak słusznie zauważysz, w kontekście wydaje się to bezsensowne
Michael K. Borregaard,