Lispから可変長引数を引き算したらできること
Schemeから可変長引数を引き算したら -- Island Life
Shiroさんが面白い記事書かれてたので、前に実際に可変長引数をなくしたLispを作って発見したことを紹介します。*1
実装者とは全く別の、遊ぶ人の視点からの記事です。
この記事では意図的にマクロを一切使わないという制約のもと、いわばラムダ計算パズルをします。
左結合のカッコを省略する
少々恣意的ですが、
((compose f g) x) ;;こう書ける (compose f g x)
こういうこと、引数の数が固定なのでカッコを省略しても一意に評価できます。関数を返す高階関数を使うときに便利。以下の例では全てこの仕組みを存分に活用します。
list関数もクオートも使わずにリストを作る
Shiroさんの記事で言及されていたように、可変長引数がないと (list 1 2 3 4)
ができなくて不便です。これも一工夫でうまいことできます。要するに1つずつ cons
していけばいいって話ですが、それでは面倒なので前項の仕組みを活用します。
まず cons
, car
, cdr
の仕組みを思い出してみます。
(define (cons x xs) (lambda (f) (f x xs))) (define (car xs) (xs (lambda (y ys) y))) (define (cdr xs) (xs (lambda (y ys) ys)))
こうですね。*2 2値にcons
を適用するとクロージャに評価されます。
ここでちょっと寄り道して car
と cdr
を少しシンプルにした -car
と -cdr
を作ります。
(define (-car x xs) x) (define (-cdr x xs) xs) ;;すると (cons 1 (cons 2 '()) -cdr -car) ;;=> 2
こうやって後置のリスト関数が作れるわけですね。同じ理屈で中置バージョンのcons、 <:
を作ってみます。
(define (<: x xs) (lambda (y) (cons y (cons x xs))))
時間がかかりましたがこれを左結合カッコの省略と組み合わせると、やりたかったことが実現できます。
(cons 1 '() <: 2 <: 3 <: 4 <: 5) ;;=> '(5 4 3 2 1) ;;おまけ (define (list x) (cons x '())) (list 5 <: 4 <: 3 <: 2 <: 1) ;;=> '(1 2 3 4 5)
まあ普通の list
よりはちょっと不便ですが見た目は綺麗でしょ?
リスト関数の後置、中置化
同じように他のリスト関数も後置または中置バージョンを作ると便利です。予め引数の順番を変更したリスト関数を作っておきます。
(define (map* xs f) (map f xs)) (define (filter* xs f) (filter f xs)) ;;etc (define (prefix f) (lambda (x xs) (pa$ f (cons x xs)))) (define -map (prefix map*)) (define -filter (prefix filter*)) (define -take (prefix take)) ;;etc
こうすると
(list 6 <: 5 <: 4 <: 3 <: 2 <: 1 -filter even? -map (pa$ * 2) -take 2 -fold + 0) ;;=> 20
便利でしょ?
パイプライン演算子
この仕組みで中置化できるのはなにもリスト関数だけではありません。関数合成 compose
を中置化してF#のパイプライン演算子 |>
や、clojureのスレッドマクロ ->
のような関数を作ります。例によってマクロではなくただの関数です。
(define (-> x) (lambda (f) (lambda (g) (f (g x))))) (define <- identity) (-> 2 -> (pa$ + 3) -> (pa$ * 4) <- number->string) ;;=> "20"
中置とは言っても最初の値をラップする仕組みのためにちょっと不思議な見た目になります。 ->
で計算をつないでいって、 <-
で結果を取り出します。
まとめ
- 可変長引数を撤廃することで、左結合のカッコを省略できます。
- するといろいろ面白いことができます。
続き: Gaucheで実験できるようにしてみました。
ちなみに、もうずっと触ってなくて動くかわからないんですが、実験に使ったオレオレLispはこれです。
燃え尽きプログラマと動的開発について
徳島の山奥でフロントエンドJSのための動的開発環境を作っている。関連して、会社の技術ブログでチラッと動的開発について触れた。こっちではもう少し突っ込んで書いてみる。
この記事の後半ではBirdについて触れるけれど、この記事の目的はBirdの宣伝ではなく問題提起と解決策の示唆です。一緒に開発環境について真剣に考えてみたい。
高等言語の発明から60余年、数え切れないほどのプログラミング言語があって、みんなそれぞれ気に入った言語を使ってソフトウェアを記述しているけれど、一部の例外*1を除くと、どの言語を使っても本質的な開発スタイルは一緒なのが現状だろう。ドキュメントを参照しながらエディタないしIDEでソースコードを記述し、実行して動作確認をする(テスト含む)。静的言語と動的言語の違いはソースコードの記述と実行の間にコンパイルが挟まるか否かだけだ。
これが悪いというわけじゃない。シンタックスが好きな言語なら、エディタで綺麗にハイライトされたソースを眺めてるだけで楽しいこともある。僕はRainbow Delimiterで虹色に輝くS式をPareditするだけで心が落ち着く。
でも時々、エディタと向かい合うのが辛い時がある。Joel on Software - 射撃しつつ前進で書かれているような現象で、このブログでも過去に触れた
プログラマの生産性の一番大きなファクターはその時の精神状態だ。もうこれは有無を言わさずそうなのだ。プログラミングスキルや知識やコミュニケーション能力や読解力なんかは差し置いて、ダントツで気分の問題が一番大きいのだ。管理職の方は是非参考にしてください。
話が脱線したように見えて、これがそうじゃない。気分が良い時は、お気に入りのエディタとお気に入りのキーボードでお気に入りの言語を書き殴るのが一番効率が良い。些細なデバッグに1時間や2時間かかろうとも砂糖とカフェインとニコチンで乗り切れるし、残業でも泊まりでも平気でできる。要するにハイだからだ。
でも気分が乗らない時はもうどうしようもない。エディタを開くのさえ苦痛で、画面いっぱいのソースコードなんて見た時には目は虚ろに、脳みそは粘土になって、手は勝手に⌘-tab
を叩いて僕をブラウザに引き戻す。こんなときはGmailをポチポチいじったりSlackでbotをからかったりとか軽い作業しかできない。これは皿洗いとか洗濯とかと一緒で、要するに一度やり始めてしまえばどうってことはないはずなのだ。でもプログラミングはこの状態からやり始めるまでの障壁が極端に高い気がする。
だったらGmailやSlackを弄るくらいの感覚でプログラミングができれば良いんだ。
エディタで書いて、別途動作確認というループをUIとして捉えて、その問題点を考えよう。
まずレスポンスの問題がある。普通のUIなら、なにかアクションを起こしたときにアプリケーションを切り替えて最初から実行し直して結果を確認するなんてことはあり得ない。Slackで文章を書いてEnterを押したらすぐにチャンネルに表示されるし、Gmailでスレッドのタイトルをクリックしたらすぐに本文が表示される。ゲームと一緒なのだ。アクションに対する報酬は即座に欲しい。これを 課題1 とする。
次に、イントロスペクションの問題。これにドキュメントの問題も含める。実際にプログラムを書くときは、エディタ→動作確認→エディタ→動作確認という単純なループにはならず、デバッグのために実行時情報を覗き見たり、ドキュメントを参照したりといった脇道が発生する。理想的には全部一つの画面でやりたくないですか!? これが 課題2 。
最後に、エディタの精神衛生上の問題は、きっとその圧倒的な視覚的情報量だ。そして多くの場合、表示される情報が十分整頓されていないこともストレスの原因だろう。これを 課題3 としよう。
課題1 と 課題2 の半分を解決するのが動的開発だ。ここで言う動的開発ってなんのこっちゃについては記事冒頭のリンク先を参照して頂きたい。簡単に言えばランタイムに開発する手法のことだ。開発環境自体が実行環境上のソフトウェアなのだ。書いた式はその場で評価して結果がわかるし、実行時情報についてはそもそもこれが実行時、つまりランタイムであるわけで、その場でなんでも覗き見れる。 課題2 の残り半分、つまりドキュメント問題は動的開発の定義の範疇ではないというだけで、動的開発環境にドキュメント参照機能をつけるのは簡単だ。
問題は 課題3 だ。これの解決には2つ必要なものがあると思う。コード分類の指針とGUIだ。
まず情報の整頓が十分でないとはどういうことか。
テキストファイルだとどうしても上下方向への1次元しかコードの各部分(コード片)を分けて配置する余地がないため、まったく違う役割のコード片がダラっと並んでしまいがちだ。加えて上下方向の次元は、純粋関数型言語でもない限り実行の順番というセマンティクスも持っているため、実行順に依存したコードなのかそうでないのかがはっきりしないという問題も抱えてしまう。
それぞれ疎なコード片は疎であることがはっきりするように並べたいわけで、これにはもう一つ以上の次元が必要になることを納得頂きたい。
コード片を分類する指針も必要だ 。冒頭のリンク先で紹介したSmalltalkでは、これをクラスカテゴリとクラスとメソッドカテゴリで分類していて、クラスブラウザを使ってナビゲートできるようになっている。
今回開発中のBirdでは違う方針を採った。だってオブジェクト指向じゃないから。
Birdを汎用の開発環境ではなく特定のFLUXフレームワーク専用にした意図はここにある。フレームワークを使うと、自然に各コード片は明確に分類できる。MVCでいえばモデルはモデルで纏めればいいし、ビューはビューで纏めればいいということだ。今回はFacebook流のFLUXを分解して、コンポーネントの概念をなくした簡素な(未圧縮2KB)フレームワークを使った。コンポーネントがないので、このフレームワーク用のコード片は
の4種類に分けられる。ちなみに関数型なのでストアはオブジェクトではなく、リードオンリーなオブジェクトへの参照(Clojureでいうatom)である。
この分類を使うと、こんなUIを作れる。
トランジションリスナの赤丸や、トランジションとDOMリスナのピルにホバーするとソースがプレビューできて、クリックすれば編集できる。一度に提示する情報が減り、圧迫感が軽減された。
コードの種類の次元が加わり、更にトランジションリスナは3次元になっている。エディタでの上下1次元の配置より格段に整頓されていることに同意してもらえると思う。
注意して欲しいのは、この記事ではグラフィカルプログラミングについて何も触れていないことだ。グラフィカルであることに主眼はない。インターフェースの改善を実直に行った結果こうなっただけ。
思ったより長くなってしまった。とにかくこれで課題は3つとも解決し、気分が乗らない燃え尽き状態でもGmailやSlackのようにプログラミングできそうな兆候が見えてきたのではないだろうか。
Birdを使った開発の様子をスクリーンキャストしてみた。お気楽な感じが出せただろうか。
Birdはまだ生焼けだけど、方向性は面白いんじゃないかと手前味噌ながら思っている。
面白い開発環境を作るのが流行ったら面白いなと思います。みなさんも如何でしょうか。
Birdを触ってみたい方はこちら
神山に引っ越してきました
玲音はBeOSユーザーだった!? lainのLisp開発環境を発掘!
こんばんは。アマチュアLisp考古学者の山下です。先週弊社でピザを焼きながら唐突に話題に上った、lainのHandiNAVIにLispのソースコードが表示されているシーンについて検証していきます。
幻のLisp開発環境を手に入れてコネクトワイヤードしたい!
まずは先人たちの研究によって判明している事項のまとめ:
- HandiNAVIのハードウェアのモデルはApple Newton
- OSはCopland OS Enterprise。これはMacのSystem 8の候補で、結局ヴェイパーウェアになったCopland Projectではないか
- ソースコードはCMU AIのリポジトリにある、ライフゲームのコード
- 言語はCommon Lisp
以上のことはwikipedia英語版のSerial Experiments Lainの記事にまとまっています。
ちなみに、このライフゲーム、お好みのCommon Lispのリスナーに書けば動くんですが、ちょっと見た感じ停止しないっぽいので、カウンターつけるなり、next-cycle
の頭とかに (sleep 1)
くらい入れてやると良いです。
それはさておき、今回特定したいのは、Lispを表示しているこのエディタ、開発環境の正体です。
この画像をよく見ると、一部隠れているもののウインドウのタイトルが読めます。CRowViewCL。まずはこれをGoogleサーチしてみました。
検索結果は一件。 なんと件の環境をブラウザ上に再現しているサイトが出てきます。
http://mebious.neocities.org/public_html/Infornography.html
mebious.neocities.org 謎しかないけどワイヤードの世界を体験出来ます。 誰か詳細知ってたら教えてください。 wired.entry.neocities
このページのおかげでわかったことは、CRowViewCLは実在のソフトウェアではないことと、件のエディタがIDEであるということ。確かに元画像にもIDEという文字は見て取れます。
Apple NewtonやCoplandへのリファレンスから、最初はMacかNeXTSTEPかのソフトウェアかと推理したのですが、よく観察するとどうもそうではなさそうです。
- メニューバーがウインドウに内包されている。
- フォントがChicagoだ。
Copland ProjectのPinkのスクリーンショットでも、メニューバーは画面上部にあり、Chicagoフォントが使われているのが確認できるので、アップルのシステムという線は捨てて捜査を進めました。
ではなんなのか
このページによると、各エピソードの終わりに表示される"To Be Continued"のBeのカラーリングがBe Inc.の昔のロゴをリゼンブルしているらしい。BeOSも出自からしてAppleと関係が深い。ビビビッと来ましたね。
- フォントが一致. どちらもCourier 10 BT Roman
- ウインドウの枠線が一致。1pxの線と直角を多用するBeOSの可愛らしい特徴が出ています
- メニューバーの色が一致
- メニューバーの項目、File Project Windowが一致。ツールバー右端にはみ出ている Data が決定的証拠.
- ツールバーの下の ▽sources が一致
この画面は、 CodeWarrior 1.5 for BeOSのスクリーンショットです。CodeWarriorなんて初めて聞いたけど、XCode以前に一大帝国を築いていたIDEらしいです。対応言語はC,C++,Pascal,Javaで、残念ながらCommon Lispは入っていないようです。
HandiNaviで動くLispの開発環境CRowViewCLのモデルは、Code Warrior for BeOSだということが判明しました。
また、HandiNAVIでBeOSのバイナリが走っていることから、Copland OS EnterpriseはBeOSの亜種なのではないかという仮説が立ちます。
Code Warrior for BeOSとlainを結びつける記述はどこにも発見できなかったので、きっと新発見だと思います。
せっかくなので再現画像を作ってみました。Code Warrior for BeOSのウインドウに、Emacsでハイライトしたライフゲームのソースコードをハメ込んでいます。
Reptoidsボタンがあるツールバーは依然謎のままです。昔の映像だと、他のボーダーはスムースなのにツールバーの上だけジャギってるので、ハメ込みじゃないかと思ってます。ちなみにReptoidはヒト型爬虫類のことです。あとは頼みます。
HandiNavi=Palm説 (追記 2018/09/30)
Reptoidsの出処を突き止めました。Reptoidという名前のゲームがCodeWorriorのPalm OS用SDKにサンプルとして付属していたようで、Palm,Inc.のRoger Floreというハッカーが作ったもののようです。
出典: Palm Hacker's Salon CodeWarrior講座 第2回 サンプルを改造してみる
ツールバーに注目
HandiNaviのハードウェアはApple Newtonをモデルにしているというのが定説ですが、Palm説も浮上してきました。
というわけで幻の開発環境の正体の本命は、Palm上のBeOSで動くCommon Lisp対応のCodeWorriorということになります。
p.s.
Clojure界隈楽しい & life on runtime
Clojure/West 2015のビデオ見始めたんですが、今年は豊作だったみたいですね。
多次元パラメータスペースを使ったジェネレティブアート。最高! Quilの上にMany Worldsってライブラリを作ったそうです。
前から気になってたcloxp。githubできてた。今日ちょっと触ってみて #tokyoclj で軽く紹介しました。JS版Smalltalk環境のLively Kernel上のClojureの開発環境という、超ニッチなところ攻めて来てます。ランタイムでlive object触って開発するのまじ楽しっすよ。今度のSmalltalk勉強会で日本のSmalltalker達に紹介する予定です。
ランタイムで開発といえば、ちょっと違うけどもう一つ。Figwheel。ランタイムの状態を壊すことなくトライアンドエラーサイクルを回せるってもの。こちらは普通のエディタ使えるのでマス受けしそう 。 www.youtube.com
まだいくつかしか観れてないですが、他にも面白いtalkいっぱいあります。乱数のやつとか。Clojure界隈不思議なことしてる人が多くて楽しいです。Something beyond ordinary programmingみたいなの好きな人は要チェック!
ランタイムでの開発って話でいうと実は僕も作ってるものがあって、近いうちに発表できるとこまで持って行きたいなと思ってます。Fluxアプリをブラウザ上で開発しちゃおうってもの。これはClojure関係なくてVanilla JS。まだPoCでWIP. よかったら一緒にやりましょう。
なんか久しぶりに開発意欲が湧いてきた。 #tokyoclj 行ってよかった。来週のClojureScript勉強会も行きます。
次元ベース宇宙の性質と勉強会のお知らせ
よく忘れるのでメモ。
任意のn次元空間Aからn+m次元図形aを観測できるとき、aが存在するn+m次元空間は必ずそのうちのn本の軸をAと共有している。
例えば、理想的な4次元空間(xyzw空間)に於いて、観測装置がxyz空間にあって、3次元立体がxyw空間にあるとき、この立体はxy平面に張り付いた体積0の2次元断面として観測されるはずだけど、z方向の厚みを素粒子一粒分すら持てないため光学的な観測は不可能。
重力はこういう風にはみ出てるんじゃないかっていうのがvacuum energyとかunified field theoryとかひも理論とかグラビトンの話につながる。証明が難しいけど論理的にはとても自然。
話は変わって、なんとなく勉強会というかビアバッシュでも開きたいなと思ってます。幾何学 ∪ 理論物理学 ∪ 計算機科学みたいなテーマで、ビール片手に語り合う会に興味がある方はぜひtwitterで教えてください。 Minori Yamashita (@ympbyc) | Twitter
数人でも興味ある方がいれば会場とビール確保してatndだかcompassだかなんだかで募集かけます。