Pull to refresh

Elm или функциональное программирование для веб, понятное чайнику

Website development *Functional Programming *
Недавно, просматривая интересные репозитории на github в поисках вдохновения я наткнулся на проект Elm — функциональный реактивный язык программирования, созданный для веб, потомок ML и Haskell. У меня нет большого опыта в функциональном программировании, но посмотрев посадочную страницу, я увлекся этим творением на несколько часов, позабыв о работе и окружающем мире. Меня сразу вдохновила та простота, которая, как мне казалось раньше не присуща функциональным языкам программирования.
Еще раз повторюсь, что я не силен в функциональном программировании, плохо знаком с математическими концепциями, на которых оно строится и изучению Elm удлелил, пока что, не очень много времени. Я считаю, что лучше бы эту статью написал кто-то другой, более осведомленный, но, таковых не нашлось, а до тех пор, я решил возложить эту ношу на себя, быть может, моя статья поможет кому-то открыть для себя прелести функционального программирования для веб, или по новому взглянуть на, казалось бы привычные вещи. Большинство материалов, представленных в статье взяты из официальной документации и переведены в довольно свободной форме. Всех страждующих, прошу под кат.


Для начала, давайте напишем наше первое приложение на Elm и попробуем разобраться, что же происходит. Не отходя от традиций, пусть это будет наш привет Миру.
import Html exposing (span, text)
import Html.Attributes exposing (class)


main =
  span [class "welcome-message"] [text "Hello, World!"]


Первые две строчки подключают модули Html и Html.Attributes, благодаря которым мы можем отображать и изменять HTML-элементы и их атрибуты на странице. Директива exposing позволяет нам использовать указанные в параметрах функции напряму, например вместо
Html.span

мы можем писать просто
span 


main это управляющая конструкция, которая управляет нашим приложением, большинству программ, написаных на Elm так или иначе будут содержать эту конструкцию.

Строка
 span [class "welcome-message"] [text "Hello, World!"] 
Сгенерирует простой HTML-код:
<span class="welcome-message">Hello, World!</span>


Но это все не очень интересно, ведь для генерации простого HTML-кода в одну строку нам пришлось написать целых 4 строчки на Elm, пока что не очень впечатляет, но стоит только заглянуть в основные концепции архитектуры языка и все становится на свои места.

Вся логика программ на Elm разделена на 3 понятные и простые части, уже, так или иначе, знакомые многим в веб разработке:
  • Model(модель)
  • Update(обновление)
  • View(представление)


Model(модель)
Я бы охрактеризовал модель, как состояние приложения, что отличается от того, что понимается под моделью в привычном MVC. Если выразить мою мысль более подробно, то Модель в Elm будет содержать в себе все модели в понимании MVC, необходимые в данном состоянии приложению, если таковые есть. При этом Model может быть чем-то намного более простым. Например, в следующем примере, в котором мы сделаем простой счетчик, Model будет простым целым числом(Int).

Update(обновление)
Когда дело касается обновления состояния, в игру вступает update. Здесь все не более сложно, чем с моделью. Update это функция, которая говорит КАК нам нужно изменить состояние приложения(Model)

View(представление)
Преставление это то, как мы хотим отобразить состояние нашего приложения, то есть Model.

В сухом остатке, приложение на Elm работает следующим образом:
Мы получаем запрос из внешнего мира, Используем его для того, чтобы обновить нашу модель, решаем, как хотим отобразить результат. Elm решает, как эффективно отобразить наш HTML.

Читая сухой текст, довольно трудно понять что к чему, поэтому, давайте рассмотрим обещаный пример создания счетчика

module Counter where

import Html exposing (..)
import Html.Attributes exposing (style)
import Html.Events exposing (onClick)
import StartApp


main =
  StartApp.start
    { model = 0
    , update = update
    , view = view
    }


-- MODEL

type alias Model = Int


-- UPDATE

type Action = Increment | Decrement

update : Action -> Model -> Model
update action model =
  case action of
    Increment -> model + 1
    Decrement -> model - 1


-- VIEW

view : Signal.Address Action -> Model -> Html
view address model =
  div []
    [ button [ onClick address Decrement ] [ text "-" ]
    , div [ countStyle ] [ text (toString model) ]
    , button [ onClick address Increment ] [ text "+" ]
    ]


countStyle : Attribute
countStyle =
  style
    [ ("font-size", "20px")
    , ("font-family", "monospace")
    , ("display", "inline-block")
    , ("width", "50px")
    , ("text-align", "center")
    ]


В этом примере добавилась довольно важная концепция — Action(действие). Действия позволяют нам правильно реагировать на запросы полученные из внешнего мира. В данном примере мы определили два типа действий — Increment и Decrement. И, в зависимости от полученного действия принимаем решение, как изменить нашу модель.

Кстати, разработчики предусмотрели онлайн-компилятор, для того, чтобы можно было запустить один из множества доступных примеров, или попробовать написать что-то самостоятельно. Попробуйте запустить этот пример и посмотреть, что получится!

Можно еще долго рассказывать о базовых концепциях данного языка, но я думаю, что те, кому изложенный материал показался хоть чуточку интересным, сами зайдут на официальный сайт и посмотрят все, что называется своими глазами. А еще, я призываю тех, кого не заинтересовало то, что я написал, или не понравился мой стиль изложения, зайти и все же посмотреть на Elm своими глазами. В заключение, я хочу добавить пример кода с официального сайта, который генерирует игру в пинг-понг в браузере, по-моему, изящность и простота этого языка, заслуживают внимания со стороны сообщества elm-lang.org/examples/pong
Tags:
Hubs:
Total votes 19: ↑17 and ↓2 +15
Views 31K
Comments Comments 22