Wiąz (język programowania)

Wiąz
The Elm tangram
Paradygmat Funkcjonalny
Zaprojektowany przez Evana Czaplickiego
Po raz pierwszy pojawiły się 30 marca 2012 ; 10 lat temu ( 2012-03-30 )
Wersja stabilna
0.19.1 / 21 października 2019 ; 3 lata temu ( 2019-10-21 )
Dyscyplina pisania Statyczny , silny , wywnioskowany
Licencja Pozwolenie ( poprawione BSD )
Rozszerzenia nazw plików .wiąz
Strona internetowa elm-lang .org Edit this at Wikidata
Pod wpływem
Haskell , Standard ML , OCaml , F#
Pod wpływem
Redux , Rust , Vue

Elm to specyficzny dla domeny język programowania do deklaratywnego tworzenia graficznych interfejsów użytkownika opartych na przeglądarce internetowej . Elm jest czysto funkcjonalny i został opracowany z naciskiem na użyteczność , wydajność i solidność . Reklamuje „brak wyjątków w czasie wykonywania w praktyce”, co jest możliwe dzięki statycznemu sprawdzaniu typów kompilatora Elm .

Historia

Elm został pierwotnie zaprojektowany przez Evana Czaplickiego jako jego praca dyplomowa w 2012 roku. Pierwsze wydanie Elm zawierało wiele przykładów i edytor online, który ułatwiał wypróbowanie w przeglądarce internetowej . Evan dołączył do Prezi w 2013 roku, aby pracować nad Elm, aw 2016 roku przeniósł się do NoRedInk jako inżynier Open Source, zakładając także Elm Software Foundation.

Początkowa implementacja kompilatora Elm jest ukierunkowana na języki HTML , CSS i JavaScript . Zestaw podstawowych narzędzi nadal się rozwija, teraz obejmuje REPL , menedżera pakietów , debugger podróżujący w czasie oraz instalatory dla systemów macOS i Windows. Elm posiada również ekosystem bibliotek tworzonych przez społeczność oraz Ellie , zaawansowany edytor online, który umożliwia zapisywanie pracy i włączanie bibliotek społecznościowych.

Cechy

Elm ma mały zestaw konstrukcji językowych, w tym tradycyjne if-expressions, let-expressions dla stanu lokalnego i case-expressions do dopasowywania wzorców . Jako język funkcjonalny obsługuje funkcje anonimowe , funkcje jako argumenty, a funkcje mogą zwracać funkcje, te ostatnie często przez częściowe zastosowanie funkcji curry. Funkcje są wywoływane według wartości. Jego semantyka obejmuje niezmienne wartości, funkcje bezstanowe i typowanie statyczne z wnioskowaniem o typie. Programy Elm renderują HTML za pośrednictwem wirtualnego DOM i mogą współpracować z innym kodem, używając „JavaScript jako usługi”.

Niezmienność

Wszystkie wartości w Elm są niezmienne , co oznacza, że ​​wartości nie można modyfikować po jej utworzeniu. Elm używa trwałych struktur danych do implementacji swoich tablic, zestawów i słowników w bibliotece standardowej.

Typy statyczne

Elm jest typowany statycznie. Adnotacje typu są opcjonalne (ze względu na wnioskowanie o typie), ale zdecydowanie zalecane. Adnotacje znajdują się w wierszu nad definicją (w przeciwieństwie do języków z rodziny C, w których typy i nazwy są przeplatane). Wiąz używa pojedynczego dwukropka, aby oznaczać „ma typ”.

Typy obejmują prymitywy, takie jak liczby całkowite i łańcuchy, oraz podstawowe struktury danych, takie jak listy, krotki i rekordy. Funkcje mają typy zapisane strzałkami, na przykład round : Float -> Int . Typy niestandardowe umożliwiają programiście tworzenie typów niestandardowych w celu reprezentowania danych w sposób pasujący do dziedziny problemu.

Typy mogą odnosić się do innych typów, na przykład List Int . Typy są zawsze pisane wielką literą; nazwy pisane małymi literami są zmiennymi typu. Na przykład Lista a jest listą wartości nieznanego typu. Jest to typ pustej listy i argumentu List.length , który jest niezależny od elementów listy. Istnieje kilka specjalnych typów tworzonych przez programistów w celu interakcji ze środowiskiem wykonawczym Elm. Na przykład Html Msg reprezentuje (wirtualne) drzewo DOM, którego procedury obsługi zdarzeń generują komunikaty typu Msg .

undefined JavaScript lub null pointer ), standardowa biblioteka Elm definiuje typ Maybe . Kod, który tworzy lub obsługuje wartość opcjonalną, robi to jawnie przy użyciu tego typu, a cały inny kod ma gwarancję, że wartość deklarowanego typu jest faktycznie obecna.

Elm zapewnia ograniczoną liczbę wbudowanych klas typów : liczba , która obejmuje Int i Float , aby ułatwić korzystanie z operatorów numerycznych, takich jak (+) lub (*) , porównywalna , która obejmuje liczby, znaki, ciągi znaków, listy porównywalnych rzeczy oraz krotki porównywalnych rzeczy, aby ułatwić korzystanie z operatorów porównania, oraz appendable , który zawiera ciągi znaków i listy ułatwiające konkatenację z (++) . Elm nie zapewnia mechanizmu dołączania typów niestandardowych do tych klas typów ani tworzenia nowych klas typów (zobacz sekcję Ograniczenia).

System modułów

Elm ma system modułów , który pozwala użytkownikom dzielić swój kod na mniejsze części zwane modułami. Moduły mogą ukrywać szczegóły implementacji, takie jak funkcje pomocnicze, i grupować powiązany kod. Moduły służą jako przestrzeń nazw dla importowanego kodu, takiego jak Bitwise.and . Biblioteki stron trzecich (lub pakiety) składają się z jednego lub więcej modułów i są dostępne w Bibliotece Publicznej Elm . Wszystkie biblioteki są wersjonowane zgodnie z semver , co jest wymuszane przez kompilator i inne narzędzia. Oznacza to, że usunięcie funkcji lub zmiana jej typu może być wykonana tylko w wersji głównej.

Współpraca z HTML, CSS i JavaScript

Elm używa abstrakcji zwanej portami do komunikacji z JavaScriptem . Umożliwia przepływ wartości do iz programów Elm, umożliwiając komunikację między Elm i JavaScript.

Elm ma bibliotekę o nazwie elm/html, której programista może używać do pisania HTML i CSS w Elm. Wykorzystuje wirtualne DOM , aby aktualizacje były wydajne.

Zaplecze

Elm oficjalnie nie obsługuje programowania po stronie serwera. Główny zespół programistów nie uważa tego za swój główny cel i woli skupić się na ulepszaniu doświadczenia w zakresie programowania front-end. Niemniej jednak istnieje kilka niezależnych projektów, które próbują zbadać możliwości wykorzystania Elm do zaplecza. Projekty utknęły głównie w wersji Elm 0.18.0, ponieważ nowsze nie obsługują „natywnego” kodu i niektórych innych wykorzystywanych funkcji. Istnieją dwie próby użycia Elm z BEAM (maszyna wirtualna Erlang). Jeden z projektów wykonuje Elm bezpośrednio w środowisku, podczas gdy inny kompiluje go do Elixira. Podjęto również próbę stworzenia frameworka zaplecza dla Elm opartego na infrastrukturze Node.js. Żaden z projektów nie jest gotowy do produkcji.

Architektura Wiązów

Elm Architecture to wzorzec do budowania interaktywnych aplikacji internetowych. Aplikacje Elm są naturalnie konstruowane w ten sposób, ale inne projekty mogą uznać tę koncepcję za przydatną.

Program Elm jest zawsze podzielony na trzy części:

  • Model - stan aplikacji
  • View - funkcja zamieniająca model na HTML
  • Update - funkcja aktualizująca model na podstawie komunikatów

To jest rdzeń Architektury Wiązów.

Na przykład wyobraź sobie aplikację, która wyświetla liczbę i przycisk, który zwiększa liczbę po naciśnięciu. W tym przypadku wszystko, co musimy przechowywać, to jedna liczba, więc nasz model może być tak prosty, jak typ alias Model = Int . Funkcja widoku byłaby zdefiniowana za pomocą biblioteki HTML i wyświetlałaby numer i przycisk. Aby numer został zaktualizowany, musimy mieć możliwość wysłania wiadomości do aktualizacji , co odbywa się za pomocą niestandardowego typu, takiego jak type Msg = Zwiększenie . Wartość Zwiększenie jest dołączana do przycisku zdefiniowanego w funkcji widoku w taki sposób, że gdy przycisk zostanie kliknięty przez użytkownika, Zwiększenie jest przekazywane do funkcji aktualizacji , która może zaktualizować model poprzez zwiększenie liczby.

W architekturze Elm wysyłanie komunikatów do aktualizacji jest jedynym sposobem na zmianę stanu. W bardziej zaawansowanych aplikacjach komunikaty mogą pochodzić z różnych źródeł: interakcji użytkownika, inicjalizacji modelu, wewnętrznych wywołań update , subskrypcji zdarzeń zewnętrznych (zmiana rozmiaru okna, zegar systemowy, interop JavaScript...) oraz zmian i żądań adresów URL.

Ograniczenia

Elm nie obsługuje polimorfizmu wyższego rodzaju , który oferują pokrewne języki Haskell i PureScript , ani nie obsługuje tworzenia klas typów .

Oznacza to, że na przykład Elm nie ma ogólnej funkcji mapy , która działa w wielu strukturach danych, takich jak List i Set . W Elm takie funkcje są zwykle wywoływane z kwalifikacją ich nazwy modułu, na przykład wywoływanie List.map i Set.map . W Haskell lub PureScript istniałaby tylko jedna mapa funkcji . Jest to znana prośba o funkcję, która znajduje się na przybliżonej mapie drogowej Czaplickiego od co najmniej 2015 roku.

Innym rezultatem jest duża ilość kodu standardowego w projektach średniej i dużej wielkości, jak zilustrował autor „Elm in Action” w swoim przykładzie aplikacji na jednej stronie, z prawie identycznymi fragmentami powtarzanymi w aktualizacjach, przeglądaniu, subskrypcjach, analizowaniu tras i budowaniu funkcji .

Przykładowy kod









 
    

 
  
 
    


   
      


      
   
       


    
      


      
    




    
 
     


    
  
       0     

 
            
 
       
       
        
    


  
 
    


  
 
     



  
     
          


     
  
      
           0
            
                   -- To jest komentarz jednowierszowy.  {-  To jest komentarz wielowierszowy.  Jest {- zagnieżdżalny. -}   -}  -- Tutaj definiujemy wartość o nazwie `greeting`. Typ jest wywnioskowany jako `String`.   powitanie  =  „Witaj, świecie!”  -- Najlepiej jest dodawać adnotacje typu do deklaracji najwyższego poziomu.  hello  :  String  hello  =  "Cześć."  -- Funkcje są deklarowane w ten sam sposób, z argumentami następującymi po nazwie funkcji.  add  x  y  =  x  +  y  — Ponownie najlepiej jest dodać adnotacje typu.  hypotenuse  :  Float  ->  Float  ->  Float  hypotenuse  a  b  =  sqrt  (  a  ^  2  +  b  ^  2  )  -- Możemy tworzyć funkcje lambda za pomocą składni `\[arg] -> [wyrażenie]`.  hello  :  String  ->  String  hello  =  \  s  ->  "Cześć, "  ++  s  -- Deklaracje funkcji mogą mieć anonimowe nazwy parametrów oznaczone przez `_`, które są dopasowywane, ale nie są używane w treści.  const  :  a  ->  b  ->  a  const  k  _  =  k  -- Funkcje są również curry; tutaj skróciliśmy mnożenie   -- operator wrostka z `2`  pomnóż przez2  :  liczba  ->  liczba  pomnóż przez2  =  (*)  2  -- Wyrażenia-if są używane do rozgałęzienia na wartościach `Bool` wartość  bezwzględna  :  liczba  ->  liczba wartość  bezwzględna  liczba  =  if  number  <  then  negate  number  else  number  -- Rekordy są używane do przechowywania wartości z nazwanymi polami  book  :  {  title  :  String  ,  autor  :  String  ,  pages  :  Int  }  book  =  {  title  =  "Steppenwolf"  ,  autor  =  "Hesse"  ,  pages  =  237  }  — Dostęp do rekordu odbywa się za pomocą `.`  title  :  String  title  =  book  .  title -- Dostęp do rekordu `.` może być również użyty jako   autor  funkcji  :  String  Author  =  .  księga  autora  -- Możemy tworzyć związki ze znacznikami za pomocą słowa kluczowego `type`.  -- Poniższa wartość reprezentuje drzewo binarne.  wpisz  Drzewo  a  =  Puste  |  Węzeł  a  (  Drzewo  a  )  (  Drzewo  a  )  — Możliwe jest sprawdzenie tych typów za pomocą wyrażeń wielkości liter.  głębokość  :  Drzewo  a  ->  Int  głębokość  drzewa  =  drzewo  przypadku  Pusty  ->  Węzeł  _  lewy  prawy  -  >  1  +  max  (  głębokość  lewa  )  (  głębokość  prawa  ) 

Zobacz też

  • PureScript : ściśle typowany, czysto funkcjonalny język programowania, który kompiluje się do JavaScript
  • Powód : Rozszerzenie składni i łańcuch narzędzi dla OCaml , które można również transponować do JavaScript

Linki zewnętrzne