トップ 追記

Catra's Diary

2005|01|02|03|05|06|07|10|
2006|05|07|09|10|11|
2007|06|07|08|
2008|01|02|07|09|11|12|
2009|06|
2010|03|07|
2011|01|
2013|05|

2013-05-05 [Sunday]

_ hsenv について

Haskell 環境をローカル(プロジェクト毎)に生成するコマンド hsenv <URL:http://hackage.haskell.org/package/hsenv>

rbenv & ruby-build を調べたのはついでで、実際はこちらが先。 hsenv は python の virtualenv を参考に作ったとあり、似たようなものに rvm があるなあ、 と見てみると最近は rbenv の方が好まれているらしい。 ということで調べてみたら、結構おもしろかったのでまとめてみた。

hsenv は、最初は rbenv のように ghc の各バージョンや、ghc 以外の Haskell を切り替えて使えるようなツールかと思っていたが、 どちらかというと cabal-dev に近く、 hsenv コマンドを実行したカレントディレクトリに .hsenv/ を生成しその下に必要なパッケージをインストールしていく形。 cabal-dev install ではなく cabal install を使えるように .hsenv/bin/ 以下に ghc, ghci, ghc-mod, runghc, cabal、そしてそれらを有効にする activate を置く。 source activate をしたシェルを使っている間(exit するまで)、 または deactivate_hsenv を実行するまでは、cabal install したパッケージは ~/.cabal/ 以下ではなく .hsenv/cabal/ 以下にインストールされ、system(global) や user へ影響しないようにする。 (※Haskell は The Haskell 2010 report をサポートする実装が ghc しかなく、ビルドも面倒なため、 Python や Ruby と比べ他の実装と切り替えて使用するということが少ないんだろうと思う。)

以下は hsenv の説明から。

Basic usage.

まず、Haskell 環境をサンドボックス化したいディレクトリを選ぶ(例えば cabal 化したプロジェクトなど)。 ディレクトリに移動する。

$ cd ~/projects/foo

次に、隔離した Haskell 環境を生成する(環境ごとに1回だけ実行する)。

$ hsenv

あとは、このHaskell 環境を使いたいときに毎回、以下を実行して環境を有効化する。

$ cd ~/projects/foo
$ source .hsenv/bin/activate

これで、生成した Haskell 環境に PATH が通り、cabal のインストール先も切り替えるなどする。 cabal でインストールしたパッケージは system(global) や user へ影響しないよう、 ~/projects/foo/.hsenv/cabal 以下にインストールされる。 また、基本的なパッケージのみ(ghc と Cabal、それらが依存するパッケージ)を Haskell 環境にコピーするため、 これらのパッケージ以外の影響も受けない。

Haskell 環境を使い終わったら、以下のコマンドを実行するか、現在のシェルを終了する。

$ deactivate_hsenv

Advanced usage.

異なる GHC のバージョンを使用することができる。 開発中のコードが違うバージョン(nightly buildも含め)でのテストに使える。

まず、バイナリ配布の GHC を取得して、 以下を実行して新しい Haskell 環境を生成する。

$ hsenv --ghc=/path/to/ghc_something.tar.gz2

あとは、Basic usage 同様にして [de]activation する。

雑記

hsenv を調べたのは、penny をインストールしようとしたら、penny-lib が依存している bytestring (0.10.*) と、 既にインストールしている bytestring 0.9.2.1 がコンフリクトしており、--reinstall --force-reinstalls を指定して cabal install を実行する必要があったため。 少しスマートな方法は無いか調べてみた。

調べてみると cabal-dev と同様な仕組みであることが分かった。 実運用上は cabal-dev を使っていればよく、cabal-dev shell のようにして ./cabal-dev/ 以下にインストールしたパッケージやコマンドを実行できればより便利と思われる。 (cabalize する予定のパッケージでも、いろいろ依存関係がある大規模S/Wなら開発(設計)中は hsenv で作って、 必要なパッケージが固まってきたら *.cabal を書いて cabal-dev に移行するのがスマートかもしれない。)

結局 penny-bin パッケージをインストールする場合は、hsenv で作成した Haskell 環境に bytestring が含まれており、 それらに依存している regex-compat, regex-posix, regex-base パッケージをインストールしなおす必要があると cabal に怒られる。そのため、

$ cabal-dev install --force-reinstalls penny-bin

で、必要な cabal パッケージを含めて cabal-dev 以下に配置するしかない。

(隔離環境で hsenv や cabal-dev で新しくパッケージをインストールするのに、 既に system(global) や user にインストールしている(ビルド済みの)パッケージを元に依存関係を生成してエラーを出すのは、 cabal のバグの気がする。)


2013-05-03 [Friday]

_ rbenv, ruby-build を使って Rails の環境構築まで。

(1) 参考サイト

今更だけどrvmからrbenvに乗り換えるときの個人用メモ <URL:http://d.hatena.ne.jp/sandmark/20121122/1353625485>

rbenv & ruby-build の使い方メモ <URL:http://qiita.com/items/b07beebca21ba7ed8e7f>

OS X で rbenv を使って ruby 1.9.3 or 2.0.0 の環境を作る <URL:http://qiita.com/items/9dd797f42e7bea674705>

Rails開発環境の構築(rbenvでRuby導入からBundler、Rails導入まで) <URL:http://qiita.com/items/a60886152a4c99ce1017>

(2) rbenv, ruby-build を github からとってくる。

$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ mkdir -p ~/.rbenv/plugins
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

(3) shell の設定ファイル .profile に以下を記述する。

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

設定を反映する。 (※上記設定で $HOME/.rbenv/shims にもPATHが通る。)

(4) Ruby をインストールする。

以下でインストール可能なRubyの一覧が見れる。

$ rbenv install -l

インストール前に、make のオプションを指定しておく。 一般的にCPUコアの数+1を -j で指定しておくと効率がよい。

$ export MAKEOPTS="-j9"

1.9系の最新版をインストール

$ rbenv install 1.9.3-p392 --verbose

2.0の最新版もインストール

$ rbenv install 2.0.0-p0 --verbose

自分でコンパイルしてインストールする場合は以下の手順。 さくらインターネットのレンタルサーバだと bison が入ってなくて ruby-2.0.0-p0 が コンパイルできず、新しい bison を入れようとすると m4 が古いと怒られたので、 以下のような手順となる。 ($HOME/bin に PATH が通っている前提。 git を素の Makefile でビルドして $HOME/bin 以下にインストールしたため、 他のツールもここに入れてしまうことにする。最近契約するともう少し新しいんだろうか。 事前にデフォルト shell も .login に exec /usr/local/bin/bash -l を書いて bash にしておく(でないと上記の rbenv init が実行できない))

$ cd ~/tmp
$ wget http://www.ring.gr.jp/archives/GNU/bison/bison-2.4.3.tar.gz
$ tar zxf bison-2.4.3.tar.gz
$ cd bison-2.4.3
$ ./configure --prefix=$HOME
$ gmake install
$ cd ..
$ wget http://ftp.ruby-lang.org/pub/ruby/ruby-2.0.0-p0.tar.gz
$ tar zxf ruby-2.0.0-p0.tar.gz
$ cd ruby-2.0.0-p0
$ mkdir dist
$ ../configure --prefix=$HOME/.rbenv/versions/2.0.0-p0c
$ gmake
$ gmake install

動きとしては1.9と2.0に大きな差は無いので、2.0をデフォルトにする。

$ rbenv global 2.0.0-p0
$ rbenv rehash
$ ruby --version
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]

(5) rubygems の管理

rbenv 導入後は gem install で $HOME/.rbenv/versions/<ruby-version>/lib/ruby/gems 以下にインストールされる。 (rbenv 導入前は $HOME 以下にインストールするため --user を指定する必要がある。)

$ gem install rdtool

生成した実行ファイルを呼び出せるように、gem install 後 rbenv rehash を実行する必要がある。 ($HOME/.rbenv/versions/<ruby-version>/bin 以下にある実行ファイルを呼び出せるように $HOME/.rbenv/shims/ 以下に同名の実行ファイルを生成する)

$ rbenv rehash

これで rd2 コマンドが実行できるようになる。

ついでに nanoc も。

$ gem install nanoc
$ rbenv rehash

(6) Bundler のインストール

Bundler とは、Gemfile に必要な rubygems を記述しておくことで、 どこでも bundle install 一発で依存する rubygems をインストールすることができるようにしたもの。

Bundler: The best way to manage a Ruby application's gems <URL:http://gembundler.com/>

bundler は gem でインストール。

$ gem install bundler
$ rbenv rehash

(7) Rails のインストール。

Rails 最新版でプロジェクトを開始しようとした場合を例に進める。 一時ディレクトリを作成。

$ mkdir ~/tmp/pj
$ cd ~/tmp/pj

必要な rubygems を Gemfile に記述しておく。ここでは rails 最新版を指定。 (※インストールされたのが 3.2.13 だったので、以下はそのバージョンを前提)

source 'http://rubygems.org'
gem 'rails'

(※Rails4 はまだリリースされていなかったので、インストールには明示的なバージョン指定が必要。)

source 'http://rubygems.org'
gem 'rails', '4.0.0.rc1'

bundle コマンドで vendor/bundle 以下に rails をインストール。

$ bundle install --path vendor/bundle

インストールした rails でプロジェクト <project-name> を作成。 (--skip-bundle を指定しないと、この時点で bundle install が実行されてしまう。)

$ bundle exec rails new <project-name> --skip-bundle

生成したプロジェクトの Gemfile を元に、実際に使用する rubygems を vendor/bundle 以下に インストールする。

$ cd example
$ bundle install --path vendor/bundle

(Rails3 の場合) bundle install した rubygems の実行ファイルを実行するには bundle exec <実行ファイル> を 呼び出すが、毎回書くのは面倒なので、bin/ 以下に stub を生成しておく。 こうすると、例えば rspec を bundle でインストールした時に bundle exec rspec ではなく bin/rspec で実行することができる。

$ bundle install --binstubs

(Rails4 の場合) Rails4 から script/ が無くなり、bin/ 以下に bundle, rails, rake が生成されるようになった。 bundle install --binstubs を指定するとこれらが上書きされてしまう。 使用するコマンドについては bundle binstubs <command> で逐一追加する形となる。

$ bundle binstubs rspec

あとは .gitignore に bundle install で生成したファイル/ディレクトリを追加。

/vendor/bundle
#/bin # Rails4の変更があるので、bin/ 以下は履歴管理対象としておいた方がよいと思う。

git で履歴管理。

$ git init
$ git add .
$ git commit -m "initial."

以降、git clone した場合はまず以下のコマンドを実行することで、同じ環境が構築できる。 (Gemfile.lock がある場合(履歴管理対象とした場合)には、そのバージョンも含めて。)

$ bundle install --path vendor/bundle

Gemfile.lock を更新したい場合は bundle update を実行する。

production 環境用には、 bundle install --deployment を実行する。 この指定で、以下のような動作になる。

vendor/bundle 以下に必要な rubygems をインストールする。
Gemfile.lock を更新する。(development 環境と production 環境は必要な rubygems が異なることが多い)
(※よく分からないが、bundle package を実行していた場合の動作にも違いがある)

(※Gemfile.lock を更新するということは、bundle update と --deployment 指定のタイミングは あまり離れない方がよいということか?)


2011-01-17 [Monday]

_ nanoc について調べ物

少し前の IE の更新により、iso-2022-jp を使用したページが文字化けして表示されるようになってしまった (正確にはなると聞いて確認した)ので、良い機会と思い日記の更新を計画。 ( <URL:http://support.microsoft.com/kb/2467659/> をあてると直るらしいのだが、手元の Vista は問題解消せず。 Windows7 の方は未確認(UbuntuとWindows7デュアルブートなので再起動が面倒だった)) 10年前から変わらずほとんど手作業で更新していたので、いい加減それは無いだろう、と。 (書く時間が95%で、サーバへのアップロードくらいしか自動化していない。 非定型作業が多いなら自動化する意味はあまりないし)

欲しい機能は、

  • 静的にWEBページを生成する
  • メモ書きから適当にトピックをピックアップして出力する
  • 半分HTML/半分ローカルルールのフォーマットで書いている内容を適当に変換する
  • 同一ソースから複数サイト用のファイルを生成してアップロード
  • 今まで書いてた日記のデータはそのまま使う

というあたりが最低限。

今回追加したい機能としては、

  • 今回の問題である文字化けの回避のため、UTF-8対応
  • 数年遅れで既に廃れかけているらしいが、RSS とかの出力
  • バージョン管理と連携
  • 購入物のDBや、del.icio.us、twitter とうまく連携

あたり。

そういう機能をもつプログラムを書いてもいいが、最近は時間が取れなくて挫折しがちなので、 出来合いのものを活用することにする。で探したのが、nanoc。 選択理由としては、

  • Item に対して Filter を使う変換ルールを規定して、コンパイルする、という考え方がしっくりきた (パブリッシュするS/W、というよりそのルールをデータと一緒に管理するためのS/W)
  • DataSource をうまく使えば動的なサイト作りと同じようなことができそう。 例として deprecated だが del.icio.us と twitter が付属している。
  • Filter や DataSource は自分で拡張できる。
  • バージョン管理と多分連携可能(subversion, git, mercurial, bazaar)
  • Rubyを使用

など。(詳細は Basic Concepts を参照)

とりあえず、更新手順をどういう形とするか、 いままでのサイトに合わせたディレクトリ構造をどう出力させるのか、などを現在考え中。

ただし、一番の難点は、この nanoc のサイトを開くと firefox がフリーズすること (Ubuntu 10.10 (x86)限定。Vistaでは発生しない)。 あまりWEB上での活用事例も多くはないので、まだ他人には勧めにくい。


2010-07-16 [Friday]

_ RSpec の Matcher

概要

actual (実際に状態を確認する対象)で使用可能なメソッドを呼び出して、成否を判断する。 Matcher に使用するメソッドと、actual で呼び出されるメソッドは以下のように関係づけられる。

  • Matcher: be_〜 → actual で呼び出すメソッド: 〜?

    例えば、be_nil という名前の Matcher を指定すると、actual で呼び出す nil? を使用して判断する。 より英語として読みやすいように、be_〜、be_a_〜、be_an_〜 という指定の仕方が出来る。 (例えば be_an_instance_of(Klass) → instance_of?(Klass) という指定が可能)

    定義場所:

    lib/spec/matchers/be.rb # be_true(), be_false, be_nil, be など
    lib/spec/matchers/be_close.rb # be_close
    lib/spec/matchers/be_instance_of.rb # be_(an_)?instance_of
    lib/spec/matchers/be_kind_of.rb # be_(a_)?kind_of
    lib/spec/matchers/method_missing.rb  # ここ経由で Spec::Matcher::BePredicate (be.rb) から他の be_〜 形式が呼び出される。
  • Matcher: have_〜 → actual で呼び出すメソッド: has_〜?

    be_〜 と同様に名前を読み替えて、呼び出すメソッドで確認する。

  • Matcher: ==, <, >, <=, >=, ===, =~

    lib/spec/matchers/be.rb で定義している Spec::Matcher::BeComparedTo を使用して、 それぞれ定義されているメソッドを使用して expected と比較する。!= は使用不可(should_not == expected を使う)。

  • その他 Matcher → カスタム Matcher

定義済みの Matcher

参照先

gem server 実行後の RDoc 参照先


2010-03-02 [Tuesday]

_ キーボードショートカット(特殊キーを含んだ場合)

昨日に引き続き、特殊キーを含んだ場合のキーボードショートカットについて。

コンソールアプリケーションと GUI アプリケーションで使用可能なキーを分けるのは、 ncurses (termcap または terminfo) で対応しているキーの組み合わせかどうか、という点。 この対応表には Shift キーによる修飾があるかどうかの情報も含まれているため、 コンソールアプリケーションで特殊キー単体押下と、Shift キーなどの修飾キー + 特殊キー押下が区別できるか、 という境目も ncurses に依存する。

端末エミュレータと ncurses (termcap または terminfo) の呼び方、TERM 環境変数の値などで 動作は異なるが、ここでは GNOME 端末、ncurses-5.7、 TERM=gnome という環境で動作させている。

コンソールアプリケーションで扱える特殊キーを分類すると、以下のようになる。

  • 制御コードを出力するキー (修飾なし、Shiftキー修飾、Ctrlキー修飾、Altキー修飾)
    • TAB (0x09, BTAB, 0x09, ウインドウ切り替えのため横取り(Alt + Tab))
    • Return (0x0d, 0x0d, 0x0d, 0x1b + 0x0d)
    • ESC (0x1b, 0x1b, 0x1b, ウインドウ切り替えのため横取り(Alt + ESC))
    • Space (0x20, 0x20, InputMethod呼び出しで横取り, GNOME端末のメニュー表示で横取り)
  • 特殊キーとして認識するキー(ncurses.h で KEY_〜 の形で宣言されている場合はその名前、 それ以外は識別するための定数)
    • キー修飾かどうかが識別できるキー (修飾なし、Shiftキー修飾、Ctrlキー修飾、Altキー修飾)
      • カーソルキー右 (RIGHT, SRIGHT, 0x022b, 0x0229)
      • カーソルキー左 (LEFT, SLEFT, 0x021c, 0x021a)
      • カーソルキー上 (UP, SR, 0x0231, 0x022f)
      • カーソルキー下 (DOWN, SF, 0x0208, 0x0206)
      • Deleteキー (DC, SDC, 0x0202, 0x0200)
      • ファンクションキー(F1〜F12)
    • Ctrlキー、Altキー修飾が識別できるキー (修飾なし、Ctrlキー、Altキー修飾。Shiftキー修飾ではキーイベント自体を検出できない)
      • Page Upキー (PPAGE, 0x0226, 0x0224)
      • Page Downキー (NPAGE, 0x221, 0x021f)
    • Altキーのみ修飾が識別できるキー (修飾なし、Altキー修飾。Shiftキー、Ctrlキー修飾ではキーイベント自体を検出できない)
      • Insertキー (IC, 0x0215)
    • キー修飾が識別できない組み合わせがある場合
      • Homeキー (Shiftキー修飾でキーイベント自体を検出できない他は、すべて KEY_HOME を検出)
      • Endキー (Shiftキー修飾でキーイベント自体を検出できない他は、すべて KEY_END を検出)
      • BackSpaceキー (Alt+キーで ESC + BACKSPACE を表示する以外は、すべて KEY_BACKSPACE を検出)

コンソールアプリケーションで認識できない(端末エミュレータでブロックされるなどで通知されない)特殊キーは以下。

  • Window Manager などが横取りする特殊キー
    • F1キー (ヘルプ表示)
    • 半角/全角キー (InputMethod 呼び出しに使用)
    • PrintScreenキー (画面のスクリーンショット取得)
    • コンテキストメニューキー (コンテキストメニュー表示)
  • 一部の Shiftキーによる修飾(上記参照)
  • 一部の Ctrlキーによる修飾(上記参照)
  • Altキーによる修飾 (一部不可。しかし Gnome端末では ESC + 押下したキーという形で無理やり送信している場合もある)
  • Windowsキー
  • ScrollLockキー
  • Pauseキー
  • 変換キー
  • 無変換キー
  • カタカナひらがなキー
  • テンキーからの入力(キーボードからの入力と区別できない)

_ そもそもなぜこんなことを考えたか

というと、以下の理由。

  • xmonad のショートカットについて考えてみたときに、アプリと Window Manager で使い分けるキーの線引きを どこですればいいか迷った。
  • Emacs のキーバインドで C-; および C-: に機能を割り当てて、端末エミュレータ越しの利用ができないということがあった。

2010-03-01 [Monday]

_ キーボードショートカット

修飾キー (Ctrlキー、Altキー、場合によっては Shift キー)と組み合わせることで特殊な操作を行う、 キーボードショートカットの役割分担についてちょっと考えてみる。 なお、入力できるキーは JIS キーボード基準で考察 (101キーボードだと少し違う)。

何も修飾キーを押さない場合

この時、キーボードから入力できるのは、

  • 0x2c 〜 0x2f (','、'-'、'.'、'/')
  • 0x30 〜 0x3b ('0' 〜 '9'、':'、';')
  • 0x40 ('@')
  • 0x5b 〜 0x5e ('['、'\\'、']'、'^')
  • 0x61 〜 0x7a ('a' 〜 'z')

Shiftキーを押した場合

この時、キーボードから入力できるのは、

  • 0x21 〜 0x2b ('!'、'"'、'#'、'$'、'%'、'&'、'\''、'('、')'、'*'、'+')
  • 0x3c 〜 0x3f ('<'、'='、'>'、'?')
  • 0x41 〜 0x5a ('A' 〜 'Z')
  • 0x5f ('_')
  • 0x60 ('`')
  • 0x7b 〜 0x7e ('{'、'|'、'}'、'~')

Shift キーを押す・押さないで、ASCII の 0x21 〜 0x7e までの全範囲を入力することが出来る。 (0x20 はスペースキー、0x7f は DELETE キーなので範囲外)

Ctrlキーを押した場合

Ctrlキーを押すことで、0x00 〜 0x1f の範囲を入力することが出来る。 これは、Ctrlキーを 0x40 〜 0x5f ('@'、'A' 〜 'Z'、'['、'\\'、']'、'^'、'_') と合わせて押下し、 押されたキーから 0x40 引いた文字コードを入力したとみなすことで実現している (例:Ctrlキー + '@' → 0x00)。

ただし、通常 'A' 〜 'Z' を入力するには Shift キーを押さないといけない。 杓子定規に当てはめるとCtrlキーの時は必ず Shift キーを押さないといけないことになるが、 それは面倒なので、'A' 〜 'Z' の部分は 'a' 〜 'z' で代用する。

つまり、文字コードベースで考えると Ctrl キーと組み合わせてコードを生成できるのは、 '@'、'a' 〜 'z'、'['、'\\'、']'、'^'、'_' のキーのみ。 これ以外のキーは Ctrl キーと合わせて使用しても、対応する文字コードが無いため有効とはならない。

Altキーを押した場合

Altキーは、入力したキーに 0x80 を加えた文字コードを生成する。(例:Altキー + 'a' (0x61) → 0xe1)

_ アプリケーションに割り当てるキーボードショートカット

ここで、ショートカットに割り振ることができる修飾キーの組み合わせについて考える。

コンソールアプリケーション

まずはコンソールアプリケーション。

  • SSH などの端末エミュレータ越しに文字コードベースの操作を行うことがある (キーボードの操作はアプリケーションに文字コードで通知される)

という前提条件がある場合、ショートカットキーに使用できるのは以下のキーのみ。

  • 何も修飾キーを押さない場合
  • Shift キーを押した場合
  • Ctrl キーと '@'、'a' 〜 'z'、'['、'\\'、']'、'^'、'_' を合わせて押下した場合
  • (確実ではないが) Alt キーと、上記3形式の組み合わせの場合

他にカーソルキーやファンクションキーなどがあるが、取り合えず今は割愛。 特殊キーには、コントロールキーを用いて入力可能なもの (例:TAB キー = Ctrlキー + 'i')があるため、 それらと Ctrl キーの同時押しは認識されない、などの制限が出てくる。

GUI アプリケーション

GUI アプリケーションの場合、文字コードによる組み合わせの制限がなくなるため、 コンソールアプリケーションの場合よりも多い、以下の組み合わせが使用可能となる。

  • 何も修飾キーを押さない場合
  • Shift キーを押した場合
  • Ctrl キーを押した場合
  • Shift キーと Ctrl キーを押した場合
  • Alt キーを押した場合
  • Alt キーと Shift キーを押した場合
  • Alt キーと Ctrl キーを押した場合
  • Alt キーと Shift キーと Ctrl キーを押した場合

ウインドウシステム用

GUI アプリケーションまでで Shift キー、Ctrl キー、Alt キーの全組合わせが使用可能であるため、 ウインドウシステムのように全体に影響を与えるような機能に対してショートカットを割り当てるには、 以下のような拡張が必要となる。

  • 新しい修飾キーを追加する (例:Windows の場合、Windows キーのこと)
  • 制御コード(0x00〜0x1F)を生成しないキーと、修飾キーの組み合わせ (例:Alt + カーソルキー など)
  • 通常使用しない特殊キー同士の同時押し (例:Windows の場合、 Ctrl + Alt + Delete や、Alt + Tab など)

2009-06-08 [Monday]

_ 「役に立たない関数」を Lisp で

といいつつ役に立たない関数を定義する関数(マクロ)を。

(defmacro define-futility (fname args &rest body)
  `(defun ,fname ,args (prog1 (progn ,@body) (fset (quote ,fname) nil))))

(define-futility useless1 ()
  (+ 1 1))

(useless1)
2
(useless1)
#=> Debugger entered--Lisp error: (void-function useless1)

(define-futility useless2 (a)
  (* 2 a))

(useless2 3)
6
(useless2 3)
#=> Debugger entered--Lisp error: (void-function useless2)

関数を定義できるが、その関数が実行されると自分自身を削除する関数にする。

しかしその関数が実行されていないという情報を持っているわけだから、なんか役に立つんじゃなかろうか、などと考えたり。


2008-12-15 [Monday]

_ SPiN その5

「SPINによる設計モデル検証」(近代化学社)参照で、前回の修正。 前回の progress については説明が適切では無かったので。

  • 進行性を確認する、つまり繰り返す動作が定義されている中で指定した場所を通らずに無限に処理を継続することが無いか、 一方の処理により他方が飢餓状態に陥ることが無いか、を確認するため、必ず通る事を確認したい居場所に progress ラベルを置く。
  • 成立してはいけない性質をオートマトンで記述し、特別なプロセスとして検査したい性質を記述するため、 Never Claim という特別なプロセスを記述する。

    SPIN では有限の記号列、無限の記号列に対応したオートマトンを利用することができる。


2008-11-10 [Monday]

_ spin による検証(4)

で、だいたい動かし方が分かってきたところで PROMELA について、 と行きたい所だが、WEB に結構情報があるので(例えば、Basic Spin Manual など)、 次の例題を考え中。

基本的な形は、複数のプロセスが共通の資源(グローバル変数や channel など)に対して操作を行うモデルを実装し、以下の点を検証する形となる。

  • 処理のその時点で満たすべき条件を確認する。条件を満たさない場合をエラーとして検出する。

    assert(判定条件)
  • デッドロックでは無い終了状態に到達することを確認する。そのために、プログラム中で終了状態とみなす箇所を追加する構文がある。 (何も指定していないと、生成した全てのプロセスが最後まで実行され、かつ全ての channel が空であるときを終了状態とみなす)

    end:  /* end〜 と言うように end の3文字で始まるユニークな名前のラベルで指定する */
  • 処理が進む(無限ループに陥らない)ことを確認する。そのために、プログラム中のループで処理が進む箇所を示す構文がある。 処理が進まないループがある (= non-progress cycles がある)事を検出するには、pan.c をコンパイルするときのオプションで -DNP を渡し、 pan -l を実行する。

    progress: /* progress〜 と言うように progress の8文字で始まるユニークな名前のラベルで指定する */

後はよく分かっていない。

  • accept-state labels
  • never claims
  • trace assertion

2008-11-09 [Sunday]

_ spin による検証(3)

PAN のコンパイルオプション

PAN (Process ANalyser) をコンパイルするときに、いくつかの定義を渡すことで使用メモリのサイズや対応する機能などを変更できる。

動作を変更するコンパイルオプションとして、例えば以下がある。

gcc -DNP -o pan pan.c

これは non-progress サイクルを検出する検証器を含んだコードを生成する。

PAN の実行時オプション

pan の実行時にもいくつかのオプションを渡すことができる。

例えばコンパイル時に -DNP を指定し、pan 実行時にオプション -l を渡すことで、 non-progress cycle を検出する。

pan -l

トップ 追記