09

clojure 書いてみた日記

intra-mart Web Platform 7.2.x では以下のようなプレゼンテーションページを書いた場合

<html>
  <body>
     <!-- <imart type="string" value="hoge" ></imart>--> 
  </body>
</html>

コメントの中のimartタグは評価されず、そのまま出力される。 つまり、クライアント側に <imart type="string" value="hoge" ></imart> が(ソース表示すると)そのまま見える。 これが intra-mart Accel Platform になると挙動が変わっており、コメントの中のものも評価されるようになっている。 つまり上記を intra-mart Accel Platform で実行した場合クライアントに対して出力されるのは

<html>
  <body>
     <!-- hoge -->
  </body>
</html>

というHTMLになる。この例だと多分最終的な見た目は変わらないからいいんだけど、条件分岐を評価させないようにというつもりでコメントアウトしていると厄介なことになる。

<html>
  <body>
     <!-- <imart type="condition" validity=oValue >--> 
     必ず出力したい文字
     <!-- </imart> -->
  </body>
</html>

intra-mart Web Platform 7.2.x では必ず出力したい文字は出力されるが、 intra-mart Accel Platform ではoValueの値によっては出力されなくなる。

これがintra-mart Web Platform 7.2.x から Accel Platform へ移行する際に困った問題の一つ。

一応正規表現を使って一括である程度対応できるものの、完全にチェックするのはなかなか難しい。 正規表現仙人であれば可能なのかもしれないが、個人的にはその域に達していないので、 どうにもこれが残ってしまっていないか不安だった。

一応実案件ではテストもするので、必要な対応はできていたと思っているけど、まあ簡単にスクリプトでも書けば 精度も効率も上がるだろうなと思っていて、一つスクリプトを書いてみることにした。 言語は長いことかけてのんびり勉強している Clojure。

要件

やりたいことを予め上げておくと

  • HTMLコメントに隠された imart タグを探す。
  • 多分問題になりうる文字列は<imartとか</imart>とか。
  • 特定のフォルダ配下を一括してチェックしてファイルパスと発見した行数と内容を出力したい。
    • 勝手に問題が解消するよう編集してくれてもいいけど、怖いのでそこまではしないでおこう

成果物

まあどの程度正確にやれてるかあやしいんだけど一応以下に上げてみた https://github.com/carrotsword/commented-imart-detection

ご査収ください。

タグの文字列をある程度固定で探しているんだけど、空白なんかを正規表現で あいまいにマッチさせた方がいいのかもしれない。

Clojureについて

Clojure の勉強用に書いてみたものなので、至らない点は多々(テストは書いているけどまだ実戦に投入はしていないので)あると思うけど Clojureを書きながら普段Java/Javascriptプログラマである自分がどんなことを考えたかということを残しておきたい。

不変性(immutability) と 関数指向

基本的にはデータをどういう集合としてとらえて、ある集合から別な集合への変換をどう考えるか、 ということを考えるのに終始していた気がする。

普通にJavaでプログラミングする場合には状態の遷移はなるべく状態のライフサイクルと マッチするようなオブジェクトを(クラスとして)設計して、状態の管理はそのオブジェクトの 中に閉じ込めて考える、という感じに設計していくだろう。

(多分関数型全般の)特性として、基本的にそういう考え方ができない(あるいは推奨されない)。 データ=状態で、状態を直接変更することは許されない(わけじゃないんだけど)から、 状態を変更するという操作はある状態Aをもとに別の状態Bを生成する形になるんだろう。

その状態遷移を記述するのが関数ということになる。

なので、基本的に状態遷移の時系列がコード上は関数の羅列という形で記述される。

オブジェクト指向の場合は状態の遷移に関する操作が一か所に集まるような 設計になる(もちろんならない人もいるが)のが普通だろうが、これは必ずしも 状態の遷移を明確に記述することにはならない。 (状態の遷移の時系列は一般にオブジェクトの外側からどう呼ばれるか次第なので、 そのオブジェクトの中にはない場合が多い)

状態Aから状態Bに遷移させる関数の適用を A => B と表現するならば、コード上の記述は

A => B
B => C
C => D

といった記述になるだろう。Clojureは動的型付け言語だけど、静的型付な環境であれば、 上記のA~Dはそれぞれ異なる型となるのだろうか。 そうであれば、型さえわかればできることは自明になるのかもしれない。

ただまあ、とにかくすべてを上記のように割り切って考えられるというわけでもない。

標準ライブラリ

とにかく googlability が低いという印象。 Clojureのコードを書いているときはMacならDash、 Windowsならブラウザで公式サイトを開きっぱなしにして調べつつコードを書いていた。

まあ、悪くないんだけど、今まさに学習中なのに、自分が知らない概念にたどり着くのが難しい感じがする。 Javaだったらこう書くんだけど、をGoogle先生に聞いて、結局自分の中のJavaコードをClojureにマッピングしているだけなのではという感じがあるのだけど、たまに聞いたこともないClojure用語的なものが出てきて、適当に検索してみてもなんのことか全くわからないということがある。

自分の知らない概念がまだまだあるんだろうなあ、という漠然としたイメージだけはある。まあドキュメント上からちゃんと読めということなのかもしれない。

S式

あるデータhogeに対してAしてBしてCしたいという場合にはまあこうなる

(C (B (A hoge)))

スレッドマクロというのがあって、こう書ける

( ->> hoge
  (A)
  (B)
  (C))

分かりやすい! が、それでいいんだっけ?という気持ちになる。 結局S式わかりにくい。

REPLとかコーディングのワークフローとか

REPLで小さな関数をどんどん試しながらボトムアップにコードを書いていくのがいいらしいのだけど、その辺の感覚がまだわからない。 頭の中のコードをとりあえずガーッと書き出してしまう感じ。なので実際動かしてみるといろいろ思っていたのと違う結果になってしんどい。

デバッグの方法もまだあまりしっくりきていない。以下の記事は大いに参考にさせてもらったのだけどEmacs使いでもないのでな・・・。

ayato.hateblo.jp

遅延シーケンス

頭ではわかっていても、実際経験してみないとわからないというか、気を付けられないものだなというのを改めて知った感じ。