Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?
@nishimura

Elmをやってみたログ

More than 1 year has passed since last update.

前から気になっていたのでやってみた。
疑問はあまり解決しないまま。

まずはエディタの設定。
elm-modeに加えてflycheckelm-oraclelsp-modeなどを試してみたけど動かない。

仕方がないので取り敢えずelm-modeだけでやってみた。
C-c C-cはダメっぽい。
https://emacs.stackexchange.com/questions/50479/elm-mode-cant-compile-file
色々大きく変更する必要があるっぽい。

C-c C-lはファイル名と場所を正しくすれば動くけど、アクティブウィンドウが切り替わるのが使いづらい。

https://emacs.stackexchange.com/questions/7409/is-there-a-generic-toggle-previous-window-function
ここに書いてある設定を使って

(defun switch-to-last-window ()
  (interactive)
  (let ((win (get-mru-window t t t)))
    (unless win (error "Last window not found."))
    (let ((frame (window-frame win)))
      (raise-frame frame)
      (select-frame frame)
      (select-window win))))

(defun elm-repl-load-back ()
  (interactive)
  (elm-repl-load)
  (switch-to-last-window)
  )

(require 'elm-mode)
(add-hook 'elm-mode-hook
          (lambda ()
            ;; (elm-format-on-save-mode)
            (local-set-key (kbd "C-c C-l") 'elm-repl-load-back)
            ))

こんな感じにして、C-c C-lでアクティブウィンドウを切り替えないようにした。もっと単純な設定がある気がするが。

マニュアルを見ながら書いていく。

main =
  Browser.element
    { init = init
    , view = view
    , update = update
    , subscriptions = subscriptions
    }


init = undefined
view = undefined
update = undefined
subscriptions = undefined

というようにまずはコンパイルを通すようにしてC-c C-lをカチカチしながら進めたいんだけど、Elmだとundefinedが無い?少しずつ書くにはどうしたらいいんだろう。

分からないのでそれも置いておいて、 https://github.com/evancz/elm-architecture-tutorial この辺を適当にいじってみる。

https://qiita.com/arowM/items/dfb38d1c5f3dfde8b8bf
この辺を読んでいると、どうも合ってない気がするが…。HTMLは普通にファイルで書きたいので、The Elm Architecture じゃなくなるよね。

例えば Closure Toolsを使いつつ

goog.provide('app.main');

goog.require('goog.dom');
goog.require('ElmJs');

function runQ(){
  var q = window['q'] || [];
  for (var i = 0; i < q.length; i++){
    q[i]();
  }
  window['q'] = {
    push: function(f){
      f();
    }
  };
}

function runApp()
{
  var el = goog.dom.getElement('elm');
  console.log(el);

  var app = window['Elm']['Main']['init']({
    node: document.getElementById('elm')
  });

}

window['runApp'] = runApp;
runQ();

こんな感じにしたい。Closure Compilerでまとめて圧縮しても一応動くけど、HTMLはサーバーサイドで書いたものをそのまま使いたいんだよなー…。

ていうわけで
https://qiita.com/ymtszw/items/d195c098445476527539
この辺を参考にしつつ

port module Main exposing (..)

import Platform
import Task
import Time
import Json.Encode as Encode
import Time.Extra

main =
    Platform.worker
        { init = init
        , update = update
        , subscriptions = subscriptions
        }


-- MODEL


type alias Model =
  { zone : Time.Zone
  , time : Time.Posix
  }


init : () -> (Model, Cmd Msg)
init _ =
  ( Model Time.utc (Time.millisToPosix 0)
  , Task.perform AdjustTimeZone Time.here
  )



-- UPDATE


type Msg
  = Tick Time.Posix
  | AdjustTimeZone Time.Zone



dateToStr : Model -> String
dateToStr model =
    let
        hour =
            String.fromInt (Time.toHour model.zone model.time)
        minute =
            String.fromInt (Time.toMinute model.zone model.time)
        second =
            String.fromInt (Time.toSecond model.zone model.time)
    in
        hour ++ ":" ++ minute ++ ":" ++ second



update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    Tick newTime ->
        let newmodel = { model | time = newTime }
        in
            ( newmodel
            , sender (Encode.string <| dateToStr newmodel)
            )

    AdjustTimeZone newZone ->
        let newmodel = { model | zone = newZone }
        in
            ( newmodel
            , sender (Encode.string <| dateToStr newmodel)
            )



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
  Time.every 1000 Tick

port sender : Encode.Value -> Cmd msg
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="UTF-8">
  <title>Main</title>
  <script src="main.js"></script>
</head>

<body>
  <h1>test</h1>
  <div id="elm"></div>
  <script>
    var app = Elm.Main.init();
    app.ports.sender.subscribe(
      function(a){
        document.getElementById('elm').innerHTML = a;
      }
    );
  </script>
</body>
</html>

こんなコードをテストしてみたり。

検索して出てくるPlatform.programworkerに変わった?
動くけど、こんな使い方をしていいものかどうか。

理想は
https://qiita.com/arowM/items/6c32db1f9e4b92445f3b
ここに書いてあるようなパーサー等を使いつつ、HTMLやCSSは普通に別ファイルで書きたい。
https://n314.hatenablog.com/entry/20110824/1314182177 昔自分がScalaで書いたやつ。こんな感じにタグのclassやnameを読み取って自動でバインディングしたい。
可能かどうかで言えば可能な気がするし他の言語でやるよりやりやすい気がするけど、用途がズレているのが気になる。

あと気になるのが、PHPでParsecを書いたときは超遅くなってメモリも大量に使ったんだけど、JavaScriptは大丈夫なのかね。
トランスパイル時に良い感じに最適化してくれるんかな。

2
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
2
Help us understand the problem. What is going on with this article?