文字列が数字でない場合0を返す。先頭が数字なら、可能なぶんだけ数値にする。Lispでexpect的ななにか最近存在を知りましたが、鯖やってる人にはお馴染み?らしいexpectというプログラムが存在するそうです。TCLで書かれたプログラムで、Passwordという文字列が表示されたらxxxを入力する、というような形で、対話的なコマンドを自動実行するために利用するものとのことです。PerlやPython、Rubyなどにもそれっぽいライブラリが存在し、なんとGuileにまでexpect.scmというファイルにモジュールが存在します。Lispにもあるよね・・・と思っていたら見つからないので、Guileのプログラムを一部パクって簡単なものを書いてみました。2))))タイムアウトも入力文字ごとに関数を呼ぶ機能もありませんが、取り合えず読み込んだ文字列が正規表現にマッチすると処理が実行されるようになりました。引数optionsは、後で何か付けたそうと思って書いたもので今は特に意味はありません。それにしても、Guileのモジュール名のice-9って何なんでしょう。無駄に格好良く見えます。(CLOS:シーロス、クロス)と言います。いう形式になっていますが、これは他のオブジェクト指向言語から見たらへんてこな順序で、わかりにくいかもしれません。args...)と書きたいでしょう。解決方法はいくつかあるかと思います。Protocol(MOP)という、デファクトスタンダード的なメタプログラミングの方法が用意されています。MOPを利用してみました。MOPには処理系毎の差異を吸収するラッパーライブラリも存在しますが、面倒くさいので処理系依存のコードを書いてしまいます。set-funcallable-instance-functionでセットした関数を、普通の関数と同じように呼び出すことができます。args...)という形式でメソッド呼び出しが出きるようになります。CommonLisp2010年9月23日木曜日EmacsからGhostScriptを利用するmake-comintを使ってみたかったので。grestore)S式からPostScriptへの変換は、単純に順序を入れ替えているだけなのでたいした意味が無いような気がしますが、括弧にかこわれているほうが精神が落ち着きますね。PostScript2010年9月17日金曜日ELispでobjdumpを呼んでバイト列を逆アセンブルするLinuxなどでプログラムを逆アセンブルする際には、objdumpを使うと便利です、たぶん。Emacsからobjdumpを呼んでバイト列を逆アセンブルするようなELispを書いてみました。バイト列といってもリストしか対応していませんが。ELisp超リードマクロに対抗してchar-codeの限界までリードマクロCLerはもっと他人のネタに反応すべきらしいので対抗してみた。組み込みのリーダを書き換えるのは敷居が高いので、ごく普通の方法にしました。私はSBCLで動かしましたが、CL処理系なら大抵は動くのではないでしょうか。仕様に乗っ取ったやり方のはずなのにアレゲな気配がぷんぷんする・・・。CommonLisp2010年9月13日月曜日list処理マクロmap系関数のような処理をするマクロを作ってみました。いつもどおり毒にも薬にもならない感じです。いった形で利用します。出現順にキーワードごとに決まった処理を行い、リストを操作します。Lisp)Clojureのswap!はアトムの古い値を引数にして関数を呼び出し、その結果を新しい値とします。Lispで計4パターン書いてみました。新しい値が返るfnとfn-rの違いは、古い値が関数の引数として渡される際、第1引数となるか最後の引数となるかです。1と2の違いは、返り値として古い値を返すか新しい値を返すかです。どのパターンが有用なのかは、使ってみないことには判断できないような気がします。その2C風switchをgoを使わない形に書き直して見ました。caseの実行する式の部分に、後続で処理するすべての式をぶち込んでいます。今回は明示的にブロックを抜けない限り、最後に評価された値が返ります。4)))loopマクロの箇所は、最初はmapcanで書いていたのですが、なぜか処理が止まったので書き換えました。mapcanが破壊的関数なため、maplistで段階的にアクセスしているリストの構造(clausesの一部)を変更してしまっているのだろうと思っています。mapcanの非破壊版くらい仕様に入れておいて欲しかったです。風のswitchTwitterを眺めていたらネタに出会ったので書いてみました。Lispのcaseと同様の式を書くことができます。caseと異なるのは、条件に一致した場合goで目的の処理の前に飛ぶところです。break)としない限り、一致した箇所以降の式をすべて実行します。caseと異なり、tagbodyに展開するため返り値は常にnilになります。その2昨日の続きのforマクロ。昨日のままだと、外側のletのbinding内でそんなシンボル無いです、と怒られて動かないことがあると思われるので修正.せっかくなのでgithubを活用する事にしました。http://github.com/kurohuku/for-loop現状の動作はこんな感じです。Lispにはやたらと高機能なかわりに構文がおかしなloopマクロが存在します。キーワードを使ってネストさせる必要があります(多分)。Clojureのforは多重ループ(のようなもの)を簡潔に記述できるので、似たような構文をマクロで定義してみようと思います。toに展開されるものだけです。手抜きパターンマッチのせいで:inや:rangeはキーワードでなければなりません。展開後の一番外側のletのせいで警告が出てきますし、まだまだ改良が必要なようです。C++風出力githubを試しに使ってみるテスト。streamsを使ってみました。{DDF79C9}>stream-write-stringの引数がstream-manipulatorクラスのオブジェクトの場合、manip-streamを引数としてactionスロットの関数が呼び出され、manip-streamの状態を変化させます。format関数は高機能なかわりにやたらと複雑なので、こういった書き方のほうが多少はわかりやすくなるかもしれません。CommonLisp2010年8月28日土曜日ClojureでJWindowを作るふせんちっくなウィンドウを作ってみます。無駄にクリック時の動作をかえられるようにしたりしてみました。Lispのマクロで書いてみるすでにいろいろなところで書かれているネタな気はしますが、書いてみました。->>はexpを次の式の最後の引数の位置に挿入します。Lisp)のバイナリファイルのパースっぽいものを書こうとしてみました。Lisp初めにLispの括弧ネタ(注1)に触発されて思い浮かんだネタを書いていきます。http://e-arrows.sakura.ne.jp/2010/08/is-lisp-really-has-too-many-parenthesis.html符号的プログラミングについてPerlは非常にリッチな言語です。世界はPerlでかかれているらしいです。このPerl言語のエキスパートたちが、Perlの持つリッチな機能をフル活用するプログラミングスタイルを符号的プログラミングと呼びます。Lispも非常にリッチな言語なため、符号的プログラミングを行うことができます。Lispプログラムをいかにして符号的なスタイルに変換していくかを見ていきましょう。Lispプログラム元ネタに合わせて、階乗の値を順番に表示していくプログラムを書いてみます。20)関数fact-1の内部で、関数innerを定義し、再帰呼び出しを行っています。この関数を徐々に符号的に改良していきます。名前は付けない、使わないfact-1を眺めて、まず気づく問題点は内部関数に名前を付けている点です。Lispには無名関数を作るlambdaマクロ(注2)があるので、これを利用しましょう。関数呼び出しの位置にlambdaフォームがくると特別扱いされるので、他のシンボルより特殊な存在だと思います。1))関数に名前を付けることは避けられましたが、今度はまったく同じ式を2回も記述しなければならないという問題が発生しました。関数(サブルーチン)にも言えますが、同じものはまとめてしまうのが普通でしょう。このlambdaフォームをまとめるために名前を付けてしまっては本末転倒です。そこで、共有構造を利用することにしましょう。1))これで見やすくなりました。defunもlambdaに直してみましょう。1)))setはマクロではなく関数です。第1引数のシンボルに、第2引数引数の値をセットします。setは関数スロットではなく普通の値を格納するスロットに第2引数をセットするため、関数呼び出しにはfuncallが必要となります。20)さて、本題に戻ります。内部関数の名前は消え去りましたが、この関数にはまだまだ名前がたくさん残っています。関数名から消していきましょう。関数は単純に他のシンボルにセットすればいいだけなので簡単です。20)次は変数名を消していきましょう。Lispのシンボルには値をセットするスロットが複数あるので、関数と通常の変数で同じシンボルを別々の意味で利用できます。1)))whenはマクロなので、setfで設定できません(多分)なので、他のマクロでラップしてしまいましょう。1)))lambdaと括弧を符号的にするlambdaも同じように対処できるかと思いきや、「注2」に書いたように、関数呼び出し位置に現れるlambdaフォームは特別扱いされるため、うまくいきません。3)この問題を解決するためには、自分の定義したシンボルが読み込みんむタイミングでlambdaに変化してくれれば良さそうです。Lispでは、実行時、コンパイル時(≒マクロ)の他に、読み込み時の動作を定義するリーダマクロが存在します。リーダマクロを利用すれば、問題を解決できるに違いありません。1)))ここまで書くとふと思います。この括弧の群れは符号的ではないのではないか、と。消し去ってやりましょう。$ここまでくれば後一歩です。最後に残った関数名、fact-nを取り去り、直接引数を与えて呼び出してみましょう。$終わりに最初と最後のプログラムを比べると、もはや別のプログラミング言語ではないかと思えてしまいます。Lispプログラムなのです。符号的プログラミングは、一般的なプログラミングスタイルとはかけ離れているように見え、一部のエキスパートにしか駆使することの出来ない黒魔術かのような錯覚を覚えますが、一つ一つの要素を抜き出して考えれば、私たちが日頃書いているごく普通のプログラムとかわりはありません。Perlは非常に高機能ですが敷居が高いのが難点です。Lispは一般的なスタイルのプログラムも非常に書きやすいので、符号的プログラミング入門者にもおすすめです。Lispで遊んでみてください。Lisp関数を作ってみた。M-dなどをうまく駆使すれば連打の必要はなかったのかもしれないけれど。実は組み込みで求めている機能がある、なんてことはないと信じたい。start-point))))現状、正規表現にマッチした部分は切り取らないようにしている。2010/08/15)青春18切符で京都と長野に行ってきました。近くの急な階段を昇ったところ。日本酒の古酒にときめいた。冷やし飴を始めて飲んだが、ショウガの風味があるやつで結構おいしかった。本日の酒(2010/08/04)本日の酒は、はるばるドイツからやってきたビール、ヴァルシュタイナー。輸入してるのはアイコン・ユーロパブ株式会社というとこらしい。酒2010年8月3日火曜日McCLIMで升目を描くformatting-tableを利用すれば良さそうだけど、無理やりな感じが現れてる。LispworksのCLIMのページを参考にした。World!FizzBuzzBrainfu*kというのを最初に書いてみることにしている。ClojureでもBrainfu*kを書いてみた。Clojure2010年7月25日日曜日ジンジャーエールを作る-その1今日の昼食を食べた店で、自家製ジンジャーエールがあったので頼んでみたらおいしかった。自分でも作ってみたい、そしてそのジンジャーエールでモスコミュールを作りたい、と思った。レシピを調べて見たところ、割と皆さん自分の好きなように作っているっぽかったので、簡単そうなハチミツに付けるだけのものを試してみた。粉の奴を大さじ1杯これだけ。こいつを炭酸水で割るとジンジャーエールが出来上がるらしい。シナモンが多すぎるような気がするが、入れてしまったものはしかたない。これらを瓶の中にぶち込んで冷蔵庫で放置する。まともに飲めるものができるのだろうか。with-open-fileも書いてみた。EmacsMcCLIMでグラフを書くMcCLIMでグラフを描画する。ノードが循環すると繰り返し処理をしようとして落ちるようだ。'graph-frame)))McCLIMはPostScriptを出力する事もできるらしい。open)・・・あれ?ELispってファイルオープンしてストリームを作ることができないのか・・・。調べて見たところ、streamとして使えるのは以下のとおりらしい。(関数定義)つまりはバッファを介さないとファイル入出力ができないっぽい。open/closeでストリームを扱っているつもりになれる関数を書いてみた。Cのトランスレータを書こうと前々から思っていじってはいるが、結局うまい方法を思いつけずに挫折ということを繰り返している。emitという流れにしようというもの。マクロとオブジェクトの定義部分を書こうとして、自分でも理解しきれないネストしたquasiquoteを書いたのでネタとして載せておく。Lispその他から拝借した関数などをまとめたパッケージ。Lispより3文字短い。3文字程度なら良いのだけど、Clojureにはさらに無名関数のためのリーダマクロが用意されている。%2))Clojureに心引かれる箇所は色々あるけれど、このリーダマクロなら多少は自分で書いてみることができるのでは無いかと思ったので、試しに書いてみた。展開されるようにした。引数は%nではなく$nで表現した。#'short-lambda-reader))(enable-short-lambda-reader);;example;;$1が第1引数を表す。$rは$nの中で最大のもの以降の残りの要素に束縛される。0)うーん、結構見づらいような。$1}としたほうが見やすいかもしれない。Androidで遊ぼうとしている。JavaもClojureもAndroidも素人なのでいろんなとこで時間をくってるが、とりあえずボタンクリックでAlertDialogを表示するところまでいった。show)))Btn1はres/layout/main.xml中でandroid:id="@+id/Btn1"と定義したボタン。ログの出力はandroid.util.Logクラスのstaticメソッドで行える。ネストクラス(クラスの中で定義されたクラスなど)は/ではなく$で参照するらしい。たけくま酒店」にて購入。溪は父親がどこからか購入してきた。雪吟は大学の卒業式(学位授与式)後に後輩にもらった。梵は大学の友人にもらった。田ゆうは神奈川県海老名市にある泉橋酒造で作られたものだが、使用している米は川崎で取れたものとのこと。酒屋2010年3月28日日曜日ClojureでTwitterClojureの練習がてらTwitterクライアントの作成を目指す。タイムラインを取得してJTableで表示してみた。Clojure2010年3月27日土曜日Clojure始めました2Clojureをさわり始めたので、メモ。;;空白文字が入る箇所に,(カンマ)を入れても良い。8);;mapはシーケンスの各要素を引数として関数を呼び出した結果を集めて返す。%)のように;;作成することもできる。この時、%は第1引数を、%nは第n引数を表す。10));;同様の処理はforでは以下のように書ける。;;forはループではなくリスト内包表記というらしい。;;CLと違い、forやlet,defnなどで変数束縛や仮引数を書く場所は;;丸括弧()ではなく角括弧[]で括る。81);;forにはwhenやwhileなどのキーワードを指定して式を評価する条件を与える;;ことができる。;;whenは条件が真の場合のみ本体を評価して値を集める。;;whileは条件が真の間本体を評価して値を集め、条件が偽になった時点で終了する。4);;forにキーワードwhenを与えた場合と同じような動作はfilterで行える。9);;forは変数束縛(?)を複数指定出来る。;;並行に束縛されるのではなく、多重ループのような順序で束縛される。;;後ろに書いた変数ほど先に束縛が繰り返される。"cC");;Scheme等でネタにされた'Lisp脳'的FizzBuzzは以下のように書ける。;;condはCLなどと異なり、条件式と真の時の動作を括弧では括らず順番に書く。;;:elseの箇所は偽以外ならなんでも良いと思う。b)はa/bの余りを返す。remainderの略だと思う。31)));;シーケンスは遅延評価されるため無限長のシーケンスを扱える。;;takeでシーケンスの要素を先頭から指定した個数分取り出せる。;;シーケンスは変更不可能なので、シーケンスに対する処理を行うと新しいシーケンスが作られている。;;リストのように丸括弧で表示されていても、シーケンス操作の返り値の実際のクラスはシーケンスである。'(1)))->clojure.lang.LazySeq;;マップ(hash-map)はキーと値のペアを並べたもの。;;関数として扱うこともでき、その場合は引数にキーを取り、対応する値を返す。3)->4;;キーワードは、マップからそのキーワードに対する値を取り出す関数でもある。3})->2;;ベクタも関数として扱うことができ、その場合は引数にインデックスを取る。0)->1;;関数定義にはdefnを用いる。;;mapcatはCLのmapcanのように各要素に関数を適用した後のリストを;;つなげ合わせて返すようだ。4);;リスト(というかシーケンス)の長さを返すにはcountを用いる。;;自前で実装すると、例えば以下のようになる。;;CLでは両方あるけれど、Clojureにはcar/cdrは存在せず、first/restのみ利用できる。;;また、nilは空リストでは無いので気をつける。lst)))));;ClojureではJavaの仕様上末尾再帰を最適化しないらしい。;;かわりにrecurを利用すると関数の初め(またはloop)に飛ぶ。;;相互再帰はtrampolineで行える。;;末尾再帰よりも遅延シーケンスを利用するのがClojure流らしい。;;関数は引数の個数によって動作を変える事が出来る。;;仮引数と関数本体を括弧で括ったものを列挙すれば良い。