c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programmingに分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡

音樂はSoundCloud等バラバラの場所に公開中です。申し訳ないがlinkをたどるなどして探してください。

考察は現在は主に此のblogで公表中です。

programmingは、GitHubで開発中です。

Develop Google Apps Script in ClojureScript

qiita.com🎂

What is Google Apps Script?

f:id:Kureduki_Maari:20181223190842p:plain

Google Apps Script (以下Apps Script) は、Googleのserver上でのserverlessなJavaScript實行環境です。serverlessなJavaScript實行環境ですのでCloud Functionの仲間です。函數を起動できるeventの種類が限られている、またSLA (Service Level Agreement) が不明である為、Cloud Functionのやうに大規模なserviseを作る事は、できません。代はりに、DocsやGmail等[など]のGoogle Appsと連携するやう簡單に設定できる為、この意味でVBA (Visual Basic for Applications) の仲間でもあります。更にGoogle Appsが使へる環境であれば無料です。その代はり一日当りの實效囘數等が制限されてゐます。

Apps Scriptと云へばGoogle Apps向けのVBAである、と思はれる向きもあり、GmailとSpreadsheetを同時に見たり更新したりできると云ふ使ひ途もあるのですが、cronの代はりとしてGoogle Appsに全く觸らない函數も作れます。であるので、Google Apps accountで使へるserverless FaaS (Function as a Service) だと見るのがよいです。今の所書ける言語はJavaScriptだけです。

Google Appsのweb site上にApps Scriptのeditorがあるのですが、ただのtext editorであり、version管理も難しく、複數人で編集したりtestを書いたりlibraryを使ったりする事ができません。programmerですので、日々使ってゐるeditor (Emacs) で書き、日々使ってゐるversion管理system (Git) で管理し、人間にも讀めるcodeを書きたいものです。これをお膳立てしてくれるのがclaspです。

github.com

Apps Script用のCLI toolであり、localのscriptをuploadする、Google Apps上のscriptをdownloadする、Google Apps上のscriptを實行する、Google Apps上の現在のversionにtagを打つ、Apps Scriptが吐いたlogを見る、等の事ができます。まともな開發に要る事はできさうです。人間でゐませう (發狂せずとも濟みさうと云ふ意)。

What is ClojureScript?

f:id:Kureduki_Maari:20181223190914p:plain:w128

ClojureScript (a.k.a. cljs) はClojureの實裝の一つです。Clojureと云へばJVM上のLispの一つとして生まれましたが、その後.NET CLR上でも實裝され、JavaScriptへのtranspilerも作られました。この二つはClojureと同じ或いは近しいcommunityで作られてゐます。他にもErlang VM上で動くclojerlや、Cにtranspileするclojurec (これの開發は停まってゐます) もあります。廣く實行環境を見れば、Android上で動かすlein-droid (これも開發が停まってゐます)、React Nativeで動かすRe-Natal、Unityで動くArcadia等があり、更にはGraalでJVM用のClojureをnative codeに落とせるので (GraalがMySQLに搭載されたらそこでも動く) (clojure-clrをMono LLVMに流すと云ふ手も在ります)、どこででも動きますね (Ethereumのcontract自體を書く方法は見附からないのでEthereumVMでは動きませんね)。CloduinoArduinoも弄れるみたいです。珍しい所ではQuilからProcessingで映像を描けたり、OvertoneからSuperColliderで音樂を生成したりできます。

Clojureはimmutableなdataを基礎とし、vectorやmap等のdata構造 & 使ひ易い記法を持ったLispです。Lispである事が我々にとってはまづ一つの利点ですし、dataがimmutableですから、programを抽象化し易く、concurrencyを簡單に扱へます。ClojureScriptはClojureからJavaScriptへのtranspilerです。JVMAPIは使へませんが、Clojureのcore APIの大半が使へますし、JavaScriptを簡單に呼び出せます。無論NPMも使へます。

Isomorphicと云ふ言葉は懐かしいですが、懐かしくなったからといって重要で無くなった譯ではありません。Reagent等便利なWeb frontend frameworkが在ります。

Develop Apps Script in ClojureScript.

以下の二つをinstallします。

  • cljs : Macであればbrew install clojurescriptでClojureScriptを、或いはbrew install leiningenでLeiningenを入れてproject毎にinstallします。
  • clasp : NPMを入れ、npm install -g @google/claspで入れます。

私はLeiningenでprojectを作ったので、こんなproject.cljができます。

(defproject apple-is-dead "0.1.0"
  :description "Appleの障害情報を監視し通知する"
  :url "〜〜〜"
  :license {:name "Do What The F*ck You Want To Public License"
            :url "http://sam.zoy.org/wtfpl/COPYING"}
  :plugins [[jonase/eastwood "0.3.3"]
            [lein-ancient "0.6.15"]
            [lein-cljfmt "0.5.7"]
            [lein-cljsbuild "1.1.7"]]
  :dependencies [[org.clojure/clojure "1.9.0"]
                 [org.clojure/clojurescript "1.10.439"]]
  :hooks [leiningen.cljsbuild]
  :aliases {"lint" ["run", "-m" "apple-is-dead.tasks.lint/go"]
            "release" ["run", "-m" "apple-is-dead.tasks.release/go"]}
  :cljsbuild {:builds
              [{:source-paths ["src"]
                :compiler {:main apple-is-dead.main
                           :output-to "release/main.js"
                           :output-dir "target"
                           :optimizations :advanced
                           :pretty-print false
                           :foreign-libs [{:file "src/entrypoint.js"
                                           :provides ["apple-is-dead.entrypoint"]}]
                           :externs ["src/extern.js"]}}]})

lein-cljsbuildが、LeiningenにClojureScriptをbuildするやり方を教えます。

  :hooks [leiningen.cljsbuild]
  :cljsbuild {:builds
  〜〜〜

とhookすると、lein compileでClojureScriptのfileである*.cljsを探してJavaScriptにtranspileします。

:aliasesのlintでは

prettier --write src/*.js
lein cljfmt fix
lein ancient check
lein eastwood

のやうな事をさせてゐ、releaseでは

lein compile
clasp push

のやうな事をさせてゐます。

作ったClojureScriptのproject内でclasp create 〜〜〜を叩き、Apps Script projectを作ります。この時に作られるfile達が大切なので、これらをcpしておき、これらが在るdiractoryで以後clasp commandを叩きます。

あとはClojureScriptとApps Scriptのreferenseを御覽ください。Apps Scriptではlogを見たりerrorをmailに通知する事ができますので、そこを適切に作ると運用が樂になります。errorをcatchする時は(js/console.error err)でlogを吐く、實行の重要なstep毎に(js/console.info message)でlogを吐く、catchすべきでないerrorをcatchしない、retryされてもよいやうに冪等にする等、batch處理を書く時と似た事を注意する筈です。

:foreign-libs:externsは載せておきます。

                           :foreign-libs [{:file "src/entrypoint.js"
                                           :provides ["apple-is-dead.entrypoint"]}]
                           :externs ["src/extern.js"]

:foreign-libsJavaScriptからClojureScriptを呼ぶ時に要ります。Apps Scriptは書かれたものがJavaScriptであらうと前提して呼び出しますから、JavaScript側から呼べるinterfaceを開けておかなければなりません。ここに指定したfileにJavaScriptを書いておくと、それはClosure Compiler (ClojureScriptがClosure Compilerを呼び出して、codeを圧縮したりdead codeを消したりします) で變換されずに、出力されるJavaScriptにそのまま載ります。

// entrypoint.js
function main(evt) {
  apple_is_dead.main.main();
}
; main.cljs
(defn ^:export main []
  (doseq [service ((apple.get-status) :services)]
    (check-apple-service service)))

これでApps Scriptはmain()を呼び出せ、それによりapple_is_dead.main.main()、すなはち(apple-is-dead.main.main)を實行できます。

:externsは、Closure Compilerが圧縮してはいけない變數名を列擧するfileです。これらは外の環境にglobalに定義されてゐるから、このままの名前で呼び出さなければならない、例えばJavaScriptのcoreに定義されたmodule達ですが、これらはどうやらClosure Compilerが既に知ってゐます。しかしClosure CompilerはApps Scriptの事は知りません。それでもClosure Compilerはたいていうまくやりますが、一部見逃してしまふやうです。私の場合はCacheServiceの事は教えてやらねばなりませんでした (他にも色々呼び出したのですが、これ以外はうまく、圧縮せずにゐてくれました) (Closure Scriptの實裝を読んでゐないのが惡いのですが)。

// extern.js
var CacheService = {};
CacheService.getScriptCache = function() {};

これでClojureScriptでApps Scriptを開發できると思ひます。