Lisp処理系なので、Javaのライブラリが利用できます。CommonLisp2013年12月20日金曜日ABCLでClojureっぽい記法でJavaと連携gistに書きました。Lisp処理系ですが、Javaの機能を呼び出す方法が面倒くさいかんじなのでClojure風の記法でアクセスできるようにするリーダマクロを書いてみました。VBAといった高級言語で作られています。多くのプログラマにとっては、もはやアセンブリは直接書く必要のないものなのかもしれません。アセンブリを学ぶことで普段使っているOSやコンパイラやVMが一体何をしているのかを学ぶ手助けとなるのではないかと思います。低レイヤーもカバーするプログラマを目指して、アセンブリ言語をアセンブラでアセンブルして実行してみましょう。最初にアセンブラを用意しましょう。ここ(http://ccl.clozure.com/)からダウンロードできます。アセンブリを書くための作業環境として、パッケージを作成しておきます。:asm)まずは2つの整数を加算する関数を書いてみます。1行ずつ解説もつけてみました。add2という関数を定義します。引数はaとbで、それぞれレジスタarg_yとarg_zを使って渡します。arg_yとarg_zはそれぞれRDIとRSIの別名です。引数が2つかどうかチェックします。引数同士を加算してbに保存します。b(arg_z)に保存した値を戻り値として関数を終了します。条件分岐のサンプルとして、引数が1のときに1を、それ以外の時に0を返す関数を作成します。アセンブリの条件分岐は、cmp命令やtest命令で比較処理時に設定されるフラグを使った条件付きのジャンプ命令で行います。戻り値のデフォルト値として1(1である)を設定します。RAXと測値1を比較します。ENDラベルまでジャンプします。戻り値に0(1でない)を設定します。CPUID最後にCPUID命令を実行して情報を取得する関数を作成します。CPUIDはEAXレジスタに取得したい情報の種類を指定して呼び出すと、EAX、EBX、ECX、EDXに情報を格納してくれる命令です。CPUID(Wikipedia)引数に取得する情報の種類を取り、4つのレジスタの値を返す関数を作成してみます。自由に使えるレジスタが少ないっぽいので一旦スタックに積んだりしてます。2日目でタグの話題がありましたが、CCLはポインタにタグが付いてるタイプのLispです。Lisp側から整数の1を渡したつもりでも機械語としてはタグの分(ここでは3bit)ずれた値になってしまいます。box/unboxはこのずれを補正するための処理で、実際には掛け算やシフトが行われています。fn))は、関数のポインタに関数を表すタグ(7)をつけた値をfnレジスタに設定する処理らしい。この命令のバイト数が7になることを利用しているっぽい。Lispには、戻り値を作り出すために元々の構造を破壊する関数があります。除く破壊的な関数には対応する非破壊的な関数があるので、基本的には非破壊版を利用しておいたほうが良さそうです。あたりを見ると良いでしょう。CommonLisp2013年9月16日月曜日[D]デザインパターン修行:BuilderパターンBuilderパターンは複雑なオブジェクトの生成を抽象化するデザインパターン。Builderインターフェースオブジェクトの組み立てに使うメソッドを定義するDirectorクラスBuilderのメソッドを適切な順序で使ってオブジェクトを組み立てるConcreteBuilderクラスBuilderで定義したメソッドを実装するBuilderパターンをD言語で書いてみます。いうloopマクロに似たイテレーションライブラリが紹介されていました。OOPのデザインパターンに出てくる(has-next/nextを使った)イテレーターパターンっぽいコードでループできるようにしてみました。iterator-nextとhas-next-pを使ったループをiterateに組み込む。CommonLisp2013年8月8日木曜日[Emacs]helmでeshellの中でpushdされたディレクトリを表示するgistに載せました。用いると簡単にスクリーンショットが撮れるようです。Clojure2013年7月13日土曜日[C++]メンバ変数を比較してソートテンプレートを使う練習をかねて、構造体のメンバ変数同士を比較してソートしてみます。2lambda式を使えると楽で良さそう。C++11を使えればなぁ。最近、複数のサーバーのいくつかのディレクトリにファイルを転送する、という作業が必要になりました。書き直したりしました。書こうと思ったので、ftpでの転送処理を題材にしてみます。ライブラリを探すさすがにftpを実装しようと試みたりはせず、ライブラリを探します。関数を使ってそれっぽい名前のライブラリを探してみます。ファイルパスの処理も行いたいです。ファイルパスの処理用のライブラリも探してみます。使ってみることにします。ハッシュテーブルのキーと値に対するループ処理を行いたいです。loopマクロでハッシュテーブルを使おうとすると記述が面倒なので、ユーティリティマクロを定義します。自分で書くのは面倒なのでライブラリを使います。使いたいユーティリティだけを読み込むことにします。quickutilを読み込む。適当にでっちあげて実行しました。CommonLisp2013年6月16日日曜日NetBSDでEmacsを起動するまでベアボーンPCにNetBSDをインストールし、そのまま放置して1ヶ月以上が経過していました。パスワードすら忘れてしまったNetBSDにEmacsを入れるまでの道筋を忘れないようにメモ。パスワード再設定とくに使うことなく放置していたせいでパスワードを忘たので、再設定を行いました。DHCP有効化インストール時にネットワークの設定をやっていなかったようなので、DHCPを有効にしました。start起動時に有効になるよう、rc.confを書き換えました。いうパッケージ管理システムでソースからビルドするのが正義っぽいので、入れてみました。pkg_addコマンドを実行すれば良いようです。落としてくる必要があるようです。いうコンポーネントがあるようです。Markdownファイルを画面に表示してみます。Clojure2013年3月6日水曜日[Clojure]動的にライブラリを追加するnREPL経由でClojureを使っていると、再起動させずにライブラリを読み込みたいと思うことがあります。いうライブラリを使うと、動的にライブラリを取得してクラスパスに追加してくれます。leiningenのprofile.cljやproject.cljにライブラリを追加します。"0.0.13"]READMEにある例は以下のようになっています。leiningenのプラグインとして利用できるので、profile.cljの:pluginsにプラグインを追加します。"1.0.2"]カバレッジの計測対象となるプロジェクトを作成します。cloverage-testプログラムを作成します。end))))テストコードを作成します。3)))))テスト+カバレッジ計測を実行します。file:///home/kurohuku/project/cloverage-test/target/coverage/index.html以下のようなHTMLが出力されます。テストコードを追加してすべての行が実行するようにしてみます。Clojure2013年3月5日火曜日[Clojure]LWJGLをでOpenGLLWJGLでOpenGLの画面を表示してみます。Javaで書くのと大差無いです。(start)CやC++でOpenGLを書く必要に迫られたら、プロトタイプをClojureで書いてみることもできそうです。先月あたりに話題になっていたJavaの脆弱性について解説した記事を眺めてみたのでメモ。POCへのリンクもあるので文章で書かれたことがどういうコードになるのかがなんとなくわかりました。Exploits自分が理解できた(つもり)のは以下のとおり。脆弱性を利用するとこれらの制限を回避できてしまうようです。以下の2つを達成することで、任意のコードを実行できるようになるようです。利用しているようです。勉強がてらこのライブラリを利用してHelloWorldプログラムを作成してみます。javaコマンドで実行してみます。Clojureで書いたコードと対応してるように見えます。}Clojureのコンパイル時の動作を詳しく知りたい場合、このライブラリを理解しておいたほうが良さそうです。ByteArrayInputStreamを作成することで、指定した文字列を読み込むことのできるReaderを作成できます。図にしてみようと思いました。clojure.reflectを使ってインターフェースの継承関係を取得し、DOTファイルを作って図にしてみます。DOTファイルとして保存します。DOTファイルをPNG画像にするには以下のコマンドを実行すれば良いです。interface-tree.pngシーケンスに関連する部分が多いようです。戒めの意味をこめてメモ。先頭2行がヘッダで残りの行がデータ、というExcelチックなファイルを読み込んでみます。読み込む対象となる大きなCVSファイルを作成します。(rand)))))CSVファイルを読み込んで指定した関数を実行する補助関数を定義します。指定された関数に渡される際にはまだ実際の読み込み処理は行われていません。r))))CSVファイルを表すLazySeqから、先頭行を取得してみます。ID4"]この処理は即座に終了します。LazySeqのおかげで、実際に読み込まれたのは500万行あるCSVファイルのうち1行だけ(のはず)です。ヘッダを表す先頭の2行を取得してみます。java.io.BufferedReader.ensureOpenこの処理は正常に終了しません。「ストリームが既にクローズされています」という例外が発生してしまいます。返す値がLazySeqであるために起こります。その時になってから実際の読み込み処理が行われますが、このときにはもう(with-openによって)入力ストリームはクローズしています。この処理を正常に行うには、実際の読み込み処理をストリームがオープンしている間に行わなければなりません。読み込み処理を行いたいタイミングで、doallマクロで囲んだり、ベクタに変換したりしましょう。d"]]次に、ファイルの最終行を取得してみます。0.9433273177661132"]多少時間はかかりますが、正常に終了します。同様に、doseqで各行に対して処理を行うふりをしても、処理は正常に終了します。nildoseqで処理を行った後で、先頭行を取得してみます。spaceこの処理はメモリが足りないと言われて異常終了します。doseq中にGCでメモリを回収できないからだと思われます。保持する必要はないため、メモリが足りなくなることなく正常に終了します。ID4"]次に、先頭行だけでなく、先頭の2行(ヘッダ)を取得してみます。spaceこの処理は異常終了します。返す値がLazySeqであり、doseqの後までCSVの内容を保持しておく必要があるためかと思います。私はここで悩みました。「ヘッダを取得」という関数を作成したつもりでいたために返値がLazySeqであるということを忘れていました。巨大なデータを保持しなくても良いようにします。d"])ファイルに限らず、LazySeqで巨大なデータを扱うときは、処理の途中でGCできるかどうか気を付けようと思います。Clojure2013年1月25日金曜日Clojure(java)で日付を扱うClojure(Java)で日付を扱うには、java.util.Date、java.util.Calendar、java.text.SimpeDateFormatなどを使えば良さそうです。いうのがあるようです。Clojure2013年1月22日火曜日[Clojure]mapの操作Clojureでmapを作成・操作する関数のメモ。多くの関数は他のシーケンス・コレクションにも適用可能。