newLISPでプログラムを書く
アマチュア無線局を開局してからもう少しで5年。免許期間は5年で、切れる1年前から 1月前までに再申請しないと無効になる。忘れないように案内が来た。酷試に必ず出る定番 問題なんだけどね。
案内の葉書によると、申請書を地上メールで送ると3050円、電子申請だと1950円。30%OFFで お徳ですってさ。だったら、電子申請でいいじゃん。
手順は、新規ユーザー登録、1週間程するとIDとパスワードが郵送で届く。これってさりげなく 住所確認だな。IDとパスワードでログインして、申請。審査が進んでOKとなると、手数料払えの最速が 今度は電子メールで届く。ペイジー対応のATMから入金。免許状は直接取りに入ってもいいし、郵送してもらってもいいとな。
電子申請にはWindowsパソコンが必要。携帯、スマホ、タブレット、MACはお使いになれませんって、 どういう作りしてんだよー。 電波利用電子申請届出システムLiteには、 動作環境チェックをやれとな。
やってみた。ポップアップブロックがロックされるから駄目と言われた。解除したらOKに なった。使ってるWindowsとブラウザな名前、ポップアップブロックの状態とクッキーの 設定状況に○が付いたよ。一応、最初の関門はPASSだな。
それにしても、誰もがWinなパソコンなんて持ってないだろう。若い人はスマホやMACだろうに。 年寄りにターゲットを絞っておりますと、暗に主張してんだな。
TPPの障壁になると、アプル・ジュークボックス屋だかアプル時計店から文句が来るぞ。ついでに、韓国のサムスンを ないがしろにするのはけしからんと、あのおばちゃんが文句を垂れてくるぞ。さーどうする。 ソームのおばちゃん。
それよりも、国内のユーザーはこの不利益に対して、訴訟でも起さんかね。Winマシンを 持ってる人のみが優遇されてますって。8月には恒例のハムフェアがあって、今年も電子申請の 勧めなんてのをやるだろうに。その場を借りて、プラカードを掲げてデモしろよ。 行動を起さんと、舐められるぞ。
支払いは、インターネットバンキング。そんな危ない物には加入してないぞ。どうやら 郵貯のATMも使えるようだ。案内を見ようとしたら、バグ満載のアドビのやつが入ってないから 駄目と抜かしやがる。そして、ここをクリックするとフラッシュプレーヤを入れられますと、 提灯リンクが有ったぞ。
それは止めて、生身の人間に聞いてみた。昔の無線仲間。最近は空に出る事はないけど、 局免だけは維持してるとか。その人の話では、郵貯に口座があればOKとの事。 今度、郵便局へ記帳に行った時に、詳しい事聞いてこよう。
プログラム書き用の環境
ややnewLISPにも慣れてきたので、プログラムを書こうと思う。で、プログラム書き用の 環境を作っておこう。
多分、emacsにもそれ用のモードが有るだろうと思って探したら有った。 newlisp-mode 作者さんは日本人の方。2008年末から作り始めておられるようだから、オイラーは超遅い とっかかりだな。ありがたく使わしていただく。
で、OpenBSD用に少し改変。
;; $ html2txt $NEWLISPDIR/newlisp_manual.html -o newlisp_manual.txt ;; or use www-browser [File] -> [Save Page As (Text)] (defvar newlisp-manual-text "/usr/local/share/doc/newlisp/newlisp_manual.txt") (defvar newlisp-manual-html (or (dolist (path (list "/usr/local/share/doc/newlisp/manual_frame.html"
マニュアルが引けるようになってるんだけど、原稿の位置が違うので修正。 emacsからw3mを呼び出すと、レンダリングに時間がかかるので、newlisp-lookupを多用 する事にした。それ用のテキストは、w3m -dump で作ったよ。だってhtml2txtなんて コマンド持ってないもん。
その為、lookupすると、目的語が見つからんと言われた。で、newlisp-lookup-manual関数内を 下記のように修正したよ。
(format "^syntax: (%s" (regexp-quote keyword))
よくlookupするので、キーバインドに登録した。
(define-key map (kbd "C-c C-d") 'newlisp-lookup-manual)
これで、目的語の所で、C-cC-dすれば、語を拾って検索してくれる。timeの結果分解能が いくつになってるか引いたら、第二引数が有る事を知った。思わぬめっけものと喜んで います。
F5キーから起動出来るrunコマンドが装備されてるんだけど、昔の馴染みでオイラー流のrunも 登録しといた。
(defun newlisp-run (query) "newlisp run on buffer *newlisp-run-output*" (interactive (list (buffer-file-name))) (unless (string= query "") (save-buffer) (start-process-shell-command "newlisp-run" "*newlisp-run-output*" (concat "newlisp " query " " (read-from-minibuffer "args: "))) (switch-to-buffer "*newlisp-run-output*") nil)) (defun newlisp-clear-screen () (interactive) (erase-buffer)) (define-key newlisp-mode-map (kbd "\C-c\C-r") 'newlisp-run)
F5とかのキーはWindowsな人の好み。きっとWindowsの入ってるemacs23系でも動くんだろうな。 それ以前に、javaのGUIで動く、newlisp-editが有るだろうと言われそう。
JavaとフラッシュはもうWindowsで使わないと、硬く誓ったのであります。ウブとかで使うのはどうよ? portをしっかり閉めているし、使い方を限定してるから。本当にportが閉っているか? newLISPのサンプルにport-scanが付いていきたぞ。
[ob: examples]$ ./scan localhost scanning: localhost open port: 22 ssh 1024
sniffなんて言う盗聴器も用意されてた。libpcap.so.6.0 なんてのが縁の下の力持ちとして 使われてたけど、OpenBSD5.7ではいかに?
[ob: examples]$ locate libpcap.so /usr/lib/libpcap.so.8.0
デフォで入ってた。びっくりするなあと思ったてmanしたら、関連にtcpdumpが挙げられていた。 そうか、デフォで盗聴器が装備されてるんだな。
なにはともあれ、Windows上のnewLISPも、emacsから使えたんでほっとしていますよ。
constant
先のsniffのコードを見てたら、constantなんてのを使ってた。 早速マニュアルを引いてみると、へぇ、関数も保護出来るとな。それ以外のも、 『組込関数をシンボルに割り当てたり、組込関数名に他の違う関数を割り当て再定義した りすることも可能です。関数名を変更しても、性能は変わりません。』なんて書いてある。
例で、
> (+ 1 2.123) 3 > (constant '+ add) add@16D7EA90 > (+ 1 2.123) 3.123
普通のプラスは、整数演算のみ、それをconstantでaddに拡張すると、schemeっぽくなる。 これは嬉しい。是非、init.lspに入れておけ。ああ、schemeには定数として、πとかeが 定義されてるけど(これって、RnRSの要求事項?)newLISPには無い。
目指す所がPHP的だから、デフォでは無いんだな。でも普通の人が余り使わない(であろう) 財務関数や統計関数があったり、極めつけは、高速フーリエ変換とその逆関数が有ったり、 アンバランス感覚が楽しい。
そう言えば、newLISPのソースを読んでて、やたらEMSCRIPTENってのが出てくる。なんじゃらほいと思って 調べてみると、 newLISP as a JavaScript libraryって事らしい。 newlisp語をjavascript語に変換出来れば、見かけ上Webの上でnewlispを実行してる(気分に 事になる。同ページの紹介で、 ntroduction to newLISPなんて所へも 行ってみたよ。
ともあれ、定数は自分で定義しとけ
> (constant 'pi (mul 2 (acos 0.0))) 3.141592653589793 > pi 3.141592653589793 > (constant 'e (exp 1)) 2.718281828459045
血圧表示プログラム
去年さんざんやったのに、またかと言うなかれ。何か小さいスクリプトを書いておくのは、 通過儀式ですから。元データは、こんなデータ
14010121,114,66,69 14010203,116,70,57
測定日時(yymmddhh)、最高血圧、最低血圧、脈拍数が、日時順に並んだデータ。
;; bld script (module "stat.lsp") (constant 'How-many -60) ;; show last 60 data's (define (csv-read file) (let ((rv '()) (es nil) (fp (open file "read"))) (while (read-line fp) (set 'es (parse (current-line) ",")) (push (map (fn (e) (int e)) es) rv)) (close fp) (reverse rv))) (define (apm sw) (cond ((= sw 'am) (fn (e) (< (% (first e) 100) 12))) ((= sw 'pm) (fn (e) (>= (% (first e) 100) 12))) (true (fn (e) true)))) (define (ssf xfn hlp) (join (map (fn (v) (format "%6.1f" (apply xfn v))) hlp) "")) (define (ssv xfn hlp) (join (map (fn (v) (format "%6.1f" (xfn v))) hlp) "")) (define (show ds) (let ((hlp (rest (transpose ds)))) (println "Min: " (ssf min hlp)) (println "Mean: " (ssv stat:mean hlp)) (println "Max: " (ssf max hlp)) (println "Sdev: " (ssv stat:sdev hlp)))) (define (graph ds) (let ((hlp (rest (transpose ds))) (nl (fn (x) (map (fn (v i)(string i " " v)) x (sequence 0 (length x))))) (gp "plot '-' w l\n")) (push (join (nl (hlp 0)) "\n") gp -1) ;; high (push "\n\n" gp -1) (push (join (nl (hlp 1)) "\n") gp -1) ;; low (push "\nend\n" gp -1) (exec "gnuplot --persist" gp))) (set 'cv (csv-read "current.csv")) (println "at Wakeup") (show (How-many (filter (apm 'am) cv))) (println "at Night") (show (How-many (filter (apm 'pm) cv))) (println "Now Wakeup graph ... close then Night graph.") (graph (How-many (filter (apm 'am) cv))) (graph (How-many (filter (apm 'pm) cv))) (exit)
Windows7での実行結果。グラフは省略です。
C:\Users\sakae\Documents\blood>newlisp ana.lsp at Wakeup Min: 107.0 67.0 52.0 Mean: 127.2 73.1 56.3 Max: 140.0 79.0 65.0 Sdev: 6.5 2.7 2.8 at Night Min: 97.0 52.0 59.0 Mean: 112.0 63.7 62.7 Max: 130.0 75.0 70.0 Sdev: 8.5 5.3 2.3 Now Wakeup graph ... close then Night graph.
OpenBSDで実行すると、グラフ画面が2つ表示されてすぐにプロンプトへ戻るんだけど、 Windowsでは、最初のグラフ画面を消さないと、次の画面が表示されない。
gnuplotのhelpによれば、Windows用でも、 --persist が使える事になってるんだけど。 ちなみに、 --persistってのは
-p, --persist lets plot windows survive after main gnuplot program exits.
gnuplotが終了しても表示画面が残るって設定。一画面表示した所でブロックしちゃうって 事は、表示した時にgnuplot内のイベントループを回っているんだな。それを証拠に、グラフ 内でマウスを動かすと、それに応じて座標位置がリアルタイムに更新される。もしやこの 機能をoffに出来れば、すーっと抜け出してくれるかな。
もしそうなって、WindowsとUNIX系の違いでスクリプトを分ける必要が生じたら、どうする? newLISPには、そんな事もあろうかと、実行してる土台を調べる変数が用意されてる。
[ob: ~]$ newlisp newLISP v.10.6.2 32-bit on BSD IPv4/6 UTF-8, options: newlisp -h > ostype "BSD"
c:\>newlisp newLISP v.10.6.2 32-bit on Win32 IPv4/6 libffi, options: newlisp -h > ostype "Win32"
ウブとかFedoraとかのLinux系は、"Linux" って言ってくるぞ。大雑把だけど、土台が 分かるのは有り難い。
移植は、去年のGaucheのそれを引っ張ってきて修正して行った。そこはかとなくschemeチックな 所があって、相性ばつぐんでしたよ。
ただ、違う所も有ったけどね。CSVデータをカンマで分解する所。splitを使うかと思ったら、 parseなのね。
文字列を数値に変換する時は、intとかを使う。逆に数値を文字列に変換する場合、stringを 使う。このstringは汎用性があって、リストでもシンボルでも、文字列に出来る。丁度あの Haskellの表示出来るものって機能だな。(なんて言う用語だったか、すっかり蒸発してる)
zipが有るかと思ったら、mapで代用せいとな。最初のリストが尽きた所で、mapが終了する。 だから、短いリストを先に持ってくるのが常套手段。逆にすると、不足分はnilで補われる。
pushは指定が無いと、cons相当の動きをするんだけど、オプションで、-1を付けると、 最後に付け足されるようになる。(append相当)これも常套手段っぽい。
上記はオイラーが血圧監視によく使うパラメータをコード化したものだ。昔、goで汎用の やつを書いたけど、使い方は限られているから、lispに落とした次第。
ちゃんとやろうとすると、Module: getopts.lsp あたりを使って、やらなきゃならない。
統計遊び
前回もやったけど、統計関数が用意されてるんで使ってみる。
> (set 'pm (rest (transpose (How-many (filter (apm 'pm) cv))))) ((108 117 118 102 ...) (57 75 68 64 ...) (66 70 65 64 ...))
最近の就寝時のデータを取り出した。transposeなかなか便利。次は基本統計量。桁数が長いので、 roundで丸めてみた。
> (map (fn (v) (round v -3)) (stats (pm 0))) (60 112.017 7.151 8.516 72.52500000000001 0.222 -0.774) ;最高血圧 > (map (fn (v) (round v -3)) (stats (pm 1))) (60 63.667 4.256 5.303 28.124 0.136 -0.552) ;最低血圧 > (map (fn (v) (round v -3)) (stats (pm 2))) (60 62.7 1.847 2.287 5.231 0.531 0.175) ;脈拍 ; N mean sdev skew kurt
skewがいずれも正になってるから、度数分布は左偏りだな。kurtが正だと、正規分布に 比べて尖ってる。負だとなだらか。
> (map (fn (v) (round v -3)) (corr (pm 0) (pm 1))) (0.654 18.029 0.407 6.588 58 0) > (map (fn (v) (round v -3)) (corr (pm 0) (pm 2))) (-0.259 70.49299999999999 -0.07000000000000001 -2.043 58 0.046) > (map (fn (v) (round v -3)) (corr (pm 1) (pm 2))) (0.043 61.511 0.019 0.33 58 0.742)
次は、相関係数を求める。ただ一つの数が返ってくるから思ったら沢山返ってきたので、 慌てて意味を調べてみた。
name description r 相関係数 Correlation coefficient b0 回帰切片係数 Regression coefficient offset b1 回帰傾き係数 Regression coefficient slope t 優位検定の(訳注:スチューデントの)t 統計値 t - statistic for significance testing df 自由度 Degrees of freedom for t p 帰無仮説下での(訳注:スチューデントの)t の尾部両側の確率 Two tailed probability of t under the null hypothesis
相関係数を信頼するかどうかはp値の大きさによるとな。pがZEROに近ければ、信頼してよしとな。 また、
Y = b1 * X + b0
と言う、フィット直線で、一次近似が行えるともな。これ以上は統計本参照か。 統計と言えばRだけど、最近は派手な事が出来るみたいだ。 R Markdownで楽々レポートづくり
落穂拾い
上で統計関数を使った時、少数点以下が多数桁表示された。これらの表示桁数をシステム・ワイドに 変更するコマンドが用意されてる。
> (stats a) (17 3.352941176470588 1.474048442906574 1.800735143996343 3.242647058823529 0.3457226379960801 -1.039116833875074) > (pretty-print) (80 " " "%1.16g") > (pretty-print 80 " " "%1.4f") (80 " " "%1.4f") > (stats a) (17 3.3529 1.4740 1.8007 3.2426 0.3457 -1.0391)
次は、コマンドラインオプションの入手方法
[ob: ~]$ newlisp hoge.lsp aa bb cc newLISP v.10.6.2 32-bit on BSD IPv4/6 UTF-8, options: newlisp -h > $main-args ("newlisp" "hoge.lsp" "aa" "bb" "cc")
さすが、スクリプトをさっと書けるように、手厚い変数を用意してるな。
次はostypeの代わりになるやつ。サービス精神旺盛です。
> (sys-info) (455 268435456 410 1 0 2048 0 28432 10602 130)
統計情報だな。使ってるセル数とか、バージョン番号が得られる
offset description 0 Lispセルの数 Number of Lisp cells 1 Lispセルの最大数、定数 Maximum number of Lisp cells constant 2 シンボル数 Number of symbols 3 評価/再帰レベル Evaluation/recursion level 4 環境スタック・レベル Environment stack level 5 最大呼び出しスタック数、定数 Maximum call stack constant 6 親プロセスの PID または 0 Pid of the parent process or 0 7 走っている newLISP プロセスの PID Pid of running newLISP process 8 バージョンを整数で表したもの、定数 Version number as an integer constant 9 オペレーティング・システムを表す、定数: Operating system constant: (see manual)
最後に、システムが持ってる変数。正規表現でマッチした値を保持する、$n とか、 何番目の値を処理してるかを示す、$idx。この $idxはmapと組み合わせると便利。
移植したgraphの中のletで
(nl (fn (x) (map (fn (v i)(string i " " v)) x (sequence 0 (length x)))))
こんなのを定義してた。sequenceで、連番を作っていたけど、これが$idxを使うと不用に なる。
> (map (fn (v) (string $idx " " v)) '(130 122 126 120 123 129 128)) ("0 130" "1 122" "2 126" "3 120" "4 123" "5 129" "6 128")
こんな具合にgnuplotに送り込むx,yデータを作成出来る。(y軸データは、血圧値等だ)
なお、$idxは色々な所で(dolist,until,while等)使われているんで、もし番号が必要と 思ったら参照してみると良い。
最近のJS
最近はJavascriptで面白い事出来るのね。
Web Audio API + Web MIDI API】ブラウザで電子楽器を作ってみよう!
いきなり、そんなに飛ばさなくたって、と言うむきには、newLISPでそろりと始めるのが よかろう。まずは、お絵書きからだな。