ラベル 第05期 の投稿を表示しています。 すべての投稿を表示
ラベル 第05期 の投稿を表示しています。 すべての投稿を表示

2016年6月22日水曜日

第05期の区切り、またしばらくブログはお休み

第05期は、自分にとってLispと人工知能の時期でした

Lispに関する記事で初めて他の人に役に立つ情報を発信出来た。やったぜ。

bloggerに書いたこと以外でしていたこと

  • 人工知能の勉強を始めた。全部AlphaGoが悪い。成果は上がっていない。
  • やっと仕事に対する態度を自分なりに変えることができた。
  • PS4で遊んでいる。Witcher3, GravityDaze, MirrorsEdgeCatalyst,,, 堪能している。
  • ダイソンの掃除機を買った。吸いまくる。超楽しい。
  • インラインスケートとボルダリングを始めた。これはじっくり楽しい。
  • 投資の実践がやや進んだ。売買に慣れてきた。
  • 考え方とか対人関係の関係とか、そっち方面の自己啓発に足を突っ込んでみた。

期間情報

開始日:2015/08/15
終了日(宣言上):2016/04/29
日数:258日(約8か月)

最後の記事:2016/03/25

記事の更新はしていないのだが、Lispはちょっと続けていた。また何か情報を発信できるように頑張ってみたいが、無理はしない。

2016年3月25日金曜日

人工知能学習の参考図書:100万人の人工知能

初めに

ここのところ、Lispを少し離れて、人工知能について勉強している。AlphaGoやDeepLearning,TensorFlowの流れを受けて興味を持ったのだが、私自身の興味について考えるうちに、機械学習、深層学習ではなく、いわゆる「第五世代コンピュータ」の古い世代の人工知能、というより、知識の表現方法に興味を持った。

そこで各種の古い本を、図書館で借りては読んでみているのだが、その中でもこの本は、平易で、プログラミングやprologについての知識が多少あれば、古き良き人工知能の入門書としてとても良いのではないか感じた。


本の特徴

Prolog, Lisp による人工知能の開発が盛んだったころの入門書だったと思われる。主な話題は、Prolog言語による人工知能の実装について、基盤となる技術や考え方が書かれている。

簡単な例を多く取り上げて話が進められる。一つ一つの考え方やPrologでの処理の進み方を丁寧に追いかける。巻末にスリット式のステップ実行サンプルがついているという念の入りようである。s読者に考えを促す「Think」と書かれたコーナーが数多く準備されている。著者の回答が上下反転した文章で印刷されているのが印象的である。

本の中で取り上げられている話題と例

  • 第一部
    • 意味ネットワークとProlog 言語による表現
    • Prolog言語にその内容について質問する方法
      • 4人の男女の「好き・嫌い」をProlog言語で表現してみる
    • 連鎖する知識から結論を引き出す「規則」の定義
    • 新しい知識をコンピュータ(Prolog)に覚えさせる方法
      • キスをした4人の男女とカゼの連鎖
    • 再帰的な規則の定義方法
      • 病気持ちの家系図から「おたふくかぜ」持ちの親戚を持つ人を探す
    • 簡易版エキスパートシステムの実装
    • リストによる知識の扱い方の基礎
      • 羽をもち、長い首を持ち、飛ばない動物は?
  • 第二部
    • 知識を条件として持つ知識の扱い方
      • オペレーターチャート(?)
        • これが何か説明はできないが、していることはわかる、、、
    • 確率を伴う知識の扱い、ベイジアン、ファジイ、
      • ライトが切れているスクーターのバッテリーが上がっている確率は?
    • 簡単な黒板システムの実装
      • 今ミサイルを発射すべきか?
    • 学習の基礎、パターンから事実を推論する方法
      • 日焼けしやすい肌の色と髪の毛を事実から推論できるか?
        • コード例はなし。残念。
  • 第三部
    • 実際に動いているシステムの概念紹介、いずれも概念説明のみ
      • STRIPS
      • ABSTRIPS
      • MOLGEN
      • SAVOIR
      • HEARSAY
      • EXPERT-EASE
      • AM, EURISKO
      • ACT
    • 知識工学用のトゥール(13章)
      • 言語、エキスパート・システム、知識獲得用トゥール、知識工学の環境
  • 第四部
    • コンピュータは知的な生き物か?
    • いずれも「知識」とは何かの説明で難解である

この本の良かった点、そうでもない点

まず良い点は
  • 古き良き人工知能についての基礎知識を与えてくれる。その一部は今でも古びない
    • ベイジアンとか。
    • 知識ツリーとか。
    • 学習の基礎とか。
  • たいへん平易な例で作られているため、読み進めやすい。
    • 入門書としてとても良いように思われる。
  • 昔に存在した人工知能関連のシステムについて情報を得ることができる
    • 参照が3ページ
    • 知識工学用ツールの提供企業の名前と住所が載っている!
それからそうでもない点は
  • 2016年現在最新の話題には触れる気配もない
    • 深層学習、機械学習(少々触れてはいるが)
  • 後半部については今では古びていて生かすのは難しい
    • 古いシステムについての解説、解説だけなのでまた生かしづらい
    • 第四部に至っては実装や知見よりも「哲学」に近いのではないかと思う内容

この本の役立て方

この本をうまく使える人は果たしてどのような人かと想像すると
  • 人工知能について興味はあるが断片的な知識しか持っていない
  • 古い人工知能の実装に興味がある
  • 古い人工知能の研究について興味がある
  • 今書店に残っている本や情報が難しすぎると感じている、実装例が足りないと感じている
  • もっとPrologでプログラミングをしてみたいが、どの本も難しすぎる
である!、、、。あまり最近の人工知能の学習書をちゃんと呼んだわけではないし、こんな読者本当に居るのだろうか、、、?

とりあえず私が言えることは、図書館で見つけたらぜひ立ち読みしていただきたい一冊である。ということである!


2016年3月2日水曜日

CommonLisp の負の数のビット表現、ドはまりした話

初めに

Common Lisp のビット演算について調べていた私は、lognot 関数の出力を確かめようと (format t "~b" (lognot #b10110100)) のようなコードを書いていた。
しかし、その結果が -10110101 となっているのを見て、一瞬納得しかけたが、、、おかしい。本当は 01001011 ではないのか。いやまて。これは明らかにおかしい。思っていたのと違う!違うやろ?
いったい何が起こっているのか?謎を解くために私は調査に乗り出した。

概要(ネタバレ注意)

  • format 関数は、負の数値をバイナリ表示する際、
    通常の整数同様に符号部と整数部に分け、整数部のバイナリで表示する
    • ((format t "~b" (lognot #b10110100))) ;-> -10110101
    • 期待しているのは、あくまで2の補数として表現した場合の値
    • ((format t "~b" (lognot #b10110100))) ;期待は... 01001011
  • format 関数の定義では、~Dと同じに出す、基数だけ2にすると書いてある
    • その原因はおそらく、Common Lisp の”普通の整数は無限に桁が続く”仕様にあると思われる
  • 自分なりに負の数もビット表現できるような方法を考えた
  • ビット反転を伴う計算をするときぐらいにしか、おそらく問題にはならないだろう。
  • 脳内で何とかする方法として:表示された値に対して、ビット反転した値 + 1 を求め、そこに 最上位ビット 1 を加えた値が本来表示したい値である。
    • -10110101 -> 反転 -> 01001010 -> +1 -> 01001011 -> 後は最上位ビットを加える

参照

format関数でのバイナリ値の表示

最初に気付いたのは、すでに書いているが、lognot関数 の値をformat 関数に与えると、思っていたのと違う値として表示されることだった。例えば次のようになる。ちなみに、この記事は全体に SBCL 1.2.13 で動作を確認している。

* (defun show-bin (value) (format t "~b" value))

SHOW-BIN
* (show-bin 128)
10000000
NIL
* (show-bin (lognot 128))
-10000001
NIL
* #b10000001

129
* (show-bin -129)
-10000001
NIL
* (show-bin #b10110100)
10110100
NIL
* (show-bin (lognot #b10110100))
-10110101
NIL

うーん。いくつか結果を出して、その結果を計算してみて分かったのだが、どうも、format 関数は符号と整数部を分けて表示している感じがする。いや、している。
うーん。うーん。なるほどね!そうだよね、数値は符号と整数部に分けられるからね!そうだよね!。。。ちがわい。期待しているのは、ビット反転した値だわ。表示されているのは負の符号と、整数部の正のビットの値だわ。そうじゃないだわ。

~b表示 期待する表示 補足
128 10000000 0000 1000 0000
(lognot 128) -10000001 1111 0111 1111 = -129
-128 -10000000 1111 1000 0000
(lognot -128) 1111111 0000 0111 1111 = 127
-3 -11 1101
3 11 0011

こうだろ!?そうだろ!?CとかC#だったらそうしてくれるんじゃないかね!?

確認結果:format関数の仕様だった

ま、しかし、こういう挙動が起こった場合、それはCommonLisp においては「仕様を知らないだけだがね」ってなる。今回の場合も、おそらく仕様だろうと決め打って調査を開始した。
そしたら案の定だわ。format 関数の定義の一部に、~bの表示の仕様というページがあり、そこには次のように書かれていた。

~D のように表示しますが、基数のみ 2 とします。

と書いてある。~D は、意識することはないが、普通にしていたらたしかに「符号」と「整数部は正の整数で」出してくれる。すなわち、負の数値はあくまで - を付け、整数部は正の整数で表示するという仕様である。負の数値のビット表現については、とくに考慮しない。~dの表示の仕様 も確認してみたが、負の数のビット表現に関する記載は、見つけられなかった。

他に、他の表示関数 write や、表示の帰趨を決定するスペシャル変数 *print-base*を確認してみたが、負の値を私が求めているようなビット列として表示する方法に関する仕様は見つけられなかった。

なんでそうなるのか?ビット演算と2の補数に関して

Common Lisp は私が生きているよりずっと長く、私よりもはるかに賢い人たちにもまれた言語である。今は漬け込まれている。(その存在に気付いた人がおいしく食べていく)したがって、そうしているのには理由があると思われた。あるいは、”そうしないと決めた理由がどこかにあるだろう”と想像された。

ここまでの調査でひとまずわかったこととして。負の値となるような計算結果について、format 関数が、あるいは私の調べた範囲のCommonLisp の標準仕様が、思い通りの挙動をしてくれないことはわかった。しかし、どうしてこのような挙動をするのだろうか?調べていったところ、Common Lisp の整数値は、無限に桁数を持つことができる、という仕様がかかわっているように思われた。

無限に桁数を持つ整数と、負の値の表現

CommonLisp で、SBCLで初めて ビット演算を試したとき、どうやら私は暗黙に有限桁数のビット列を想像していたようである。16ビットなり、8ビットなり、64ビットなりで表現された数値を想像している。そして、暗黙にsigned, unsigned について区別して考えている。そうした場合、負の数はたった一つの表現を得ることになる。符号なしであれば、符号ありの場合に負の数にあたるビット表現に対しては、正の整数が与えられる。しかし、CommonLispの整数は違う。無限の桁数を持っている。無限に桁数を持つということはどういうことか?考えてみるにそれは、有限桁で区切ると、「そのビットより上位側のビットが0なのか、1なのかわからなくなる」ということである。

例えば、整数値を8ビットで表現してみました!といって次のような表を出すとする。

数値 下位8ビット分
1 0000 0001
127 0111 1111
180 1011 0100
-1 1111 1111
-127 1000 0000
64 1000 0000

私の頭の中では今回の例を試したとき、このような感じの頭になっていた。だが、冷静になってから見てみると、何かがおかしい。この整数の型は、なんだ?気付いてみるとものすごい違和感を覚える。-127と64が同じ表現になっていて混乱しないのか問いただしたくなる。180という数値もしれっと混ざっているが、本当に8bit整数ならunsigned じゃないと表現できないだろう、、、。型がある言語であればその上限・下限に強く意識を持つものだが、境界を持たないという定義を持つ環境では、具体的なビット表現に思いを寄せることがなくなっているのに気づく。。結局これらの値は果たして、signed なのか unsigned なのか?そもそもこの数値は、本当に8ビットで考えているのか?若干怪しい。いや、だいぶおかしい。それでいて違和感を覚えないのは、今何をしているか、どのような結果になるかについて、”内部の表現に考えを寄せることなく”想像できているためなのだろう。

さて、ビット表現の話に戻そう。たとえばバイナリ表現 1000 0000 は、次のように解釈できる。

  • signed の 8bitの値で、-127 を表している
  • unsigned の 8bitの値で、64 を表している

しかし、ビット列が上位側へ無限につながっているとしたら、次のような場合も考えられる。

  • 暗黙に 8bit以上ある値として、この後の上位ビットには 0 が続く。したがって 64 を表している
  • 表示上の最上位ビットが 1 なのだから負の値である、したがって上位ビットは1が続き、-127 を表している

そして、「いずれも正解である」と言える。単に表示に対する解釈が違うだけである。前提がはっきりしていない(もしくは自分の中でだけはっきりしている)ので一つに決められるだけではないか。

このおかしさに気付くと、そもそも負の数のビット表現ってどうやってするのだったかを思い出すことになる。先の例のいずれの整数も 16bitあればsignedの値として正常に表現できることだろう。しかし、無限に桁数があるとすれば、、、?

数値 4bit? 8bit ? signed 16 bit signed 32bit (上位24bitを省略)
1 0001 0000 0001 0000 0000 0000 0001 0..0 0000 0001
127 不可 0111 1111 0000 0000 0111 1111 0..0 0111 1111
180 不可 1011 0100 0000 0000 1011 0100 0..0 1011 0100
-1 1111 1111 1111 1111 1111 1111 1111 1..1 1111 1111
-127 不可 1000 0000 1111 1111 1000 0000 1..1 1000 0000
64 不可 1000 0000 0000 0000 1000 0000 0..0 1000 0000

無限に長さを持つということは、何ビット目を見ても、まだ上位側にビットが続いているということである。もちろん、どこかで「あるビットからは、どの上位ビットを見ても0だらけ(正)か1だらけ(負)」である状態になるのだが。

また、表示するうえでは無限にビット列を表示するわけにもいかないため、有限桁数で止めることになる。その場合に、その後続く上位側のビットが1なのか0なのか、区別がつかない可能性が残るということである。たとえば、上記の例では64 と -127 が8bit表示したところで止めてしまった場合、同じ表現に見えるということである。

そして Common Lisp の format 関数は、これらの表現とは別の表現を用いることにしているようである。符号+整数部(負であれば正の値に符号反転した値)で表現する。無限にビットが続くということを考えると、よい割り切り方だと思う。しかし、整数部をそのままビット値で表してくれるのは、、、使ってみると悩ましい。そうじゃねえ、そうじゃねえだわ。結果的に予期せぬ落とし穴になっていた。

ところで。 無限に続く上位ビットの表現に関して。

上記の例の32bit表記の際にも用いたが、便宜上 正の値は 0..0 で上位側の 0 を省略し、負の値は 1..1 で上位側の 1 を省略している。今後もそのように表記するし、表示用のコード例も同じようにしている。

どうやったらビット列を思ったような表現にできるのだろうか。

ここまでで、何が起こっているか、何を間違っていたかはおおむね分かった。だが、目的のビット表現は。今後も私は符号と整数部が分かれたformat 関数の表現を使い続けるのか。いやまあ、関数とか作ることができるだろう。format関数は、負の整数は思ったのと違う結果になるが、正の整数については正常に値を表示するのだから。単に、無限に桁数を考えたときの表示を考えてやればよいだけの話である。
手掛かりは、format関数のビット表現である。ビット表現が全くできないわけではない。正の整数であれば、思った通りの値を表示できる。では、負の数をビット表示した場合に、上位側ビットがすべて1になる前の部分を正の整数として表現できれば、何とかなる。つまり、次のように考えられる。

  • (lognot #b10110100) の値は、ビット列としては 1..101001011 と表現できる
    • #b10110100 は 180, 1..101001011 は -181
  • 整数値として、 101001011 (あるいは 0..0101001011) の値を持つ値が計算できれば、表示ができるようになる
    • 最終的なビット列表示が正しければよいので、1101001011, 11101001011,, でも間違ってはいない
    • ちなみに 0..0101001011 の値は 331, 0..01101001011 の値は 843

それを考えるには、そもそも負の値はどのようなビット列になるのか?それを10進数で表示すると一般的にはどうなるのか?考える必要がある。

2の補数について

log*系関数はいずれも2の補数であることを前提とした処理となっている。Hyperspec にも書いてある。バイナリによる負の数の表現には、2の補数を用いることが多い。負の値のビット表現は知らずのうちに2の補数による表現になっていることがある。知識として1の補数(負の数は、正の数ビット表現に対するビットごとのxorの結果に等しい)が言及されることもあるが、今回は関係ない。

2の補数とは?

その最上位ビット (MSB) よりひとつ上のビットが1で、残りが全て0であるような値
(8ビットの整数であれば、100000000(二進) = 256)から、
元の数を引いた数が2の補数である。

(Wikipedia)

他にも次の性質がある。
- 正の整数 A と、対応する負の整数(補数) -A について、足すと 最上位ビットのみ1、それ以外は0となる
- A + -A => 0..010..0 (2^n となる整数)
- 正の整数 A から、そのビット反転 ~A を求め、1 を足すことで 対応する負の整数(補数) -A となる
- -A = ~A + 1

おお、、なるほど、、、どれを使えばいいんだろう、、、。

2の補数の具体例

たとえば8ビットの値で符号ありの値を考える場合、正の値に対応する負の値は次のように表せる

正の値 正の2進数 負の値 負の2進数 正と負の値を足した結果 (9bit目あり)
127 0111 1111 -127 1000 0001 1 0000 0000
3 0000 0011 -3 1111 1101 1 0000 0000

これで無限にビット列があると想定した場合も、例えば次のように表せる。

正の値 正の2進数 負の値 負の2進数 正の値の反転
127 0..0 0111 1111 -127 1..1 1000 0001 1..1 1000 0000
3 0..0 0000 0011 -3 1..1 1111 1101 1..1 1111 1100

ほしい負の整数値のビット表現を得るために必要な正の整数値

補数についてわかったところで、今のところ現時点での目的であるビット表現に考えを戻してみる。求めたい値は何だろうか?それがほしい負の整数値のビット表現を得るために必要な正の整数値である。

う、、うん。何がほしいんだろう?えーっと。無限にビット列が続く負の値 -127 (= 1..1 1000 0000) があったとしよう。これを黙ってformat 関数に与えると、結果は -111111 (※ 127 = 0..0 0111 1111) となる。それは期待する結果ではない。そこで、一度 ビット列 1..1 1000 0000 に対して、表現だけ考えると 0..0 1000 0000 (= 64) あるいは 0..0 0001 1000 0000 (= 384),,, などを求めれば、format 関数は少なくとも一部は思った通りの値として表示できる。

数値 ビット表現 format 関数の表示
-127 1..1 1111 1000 0000 -1111111
64 0..0 0000 1000 0000 10000000
384 0..0 0001 1000 0000 110000000

あとは、format 関数の出力にしれっと 1..1 とつけてやれば、思った通りのビット表現を得られる。
残る問題は、このビット列で表現したい負の整数値(例の場合 -127)に対して、ほしいビット表現を得るための正の整数(例の場合 64, 384など)をどのように計算するかである。

ここで2の補数の定義を思い出す。CommonLispの整数値は無限に桁を持てるのだ。だから、ある整数を超える 2^n 乗の整数は容易に求められる。

  • ある負の整数値 -A のビット長 が L であるとする
    • integer-length 関数 を用いた
    • そのビットより上位ビットはすべて1であるようなビットまでの最下位からの長さ と定義できる
  • -A という整数が「あたかも (L+1) bit幅の符号付き整数値である」かのように考えてみると、、、
  • -A = 2^(L+1) - A
    • もしビット長が制限されていれば、L = ビット長、のときにこの計算で得られる値は負の値を表すビット列になる
  • Common Lisp では、ビット長に制限はないため、常に L+1 は A より大きな正の整数である。
    • 2^(L+1) - A もはやり正の整数である
  • 結果、”正の整数だが、Aの2の補数に相当するビット表現を持つ値”が得られる

負の値のビット表現をおおむね思った通りにできる関数

そうやって結論にたどり着いて最終的にできたものがこちら。

(defun show-binary (value)
  (if (>= value 0)
      (format nil "0..0~b" value)
      (let* ((sign-inverted-value (* -1 value))
             (bigger-2-power (ash 1 (+ 1 (integer-length sign-inverted-value))))
             (display-value (- bigger-2-power sign-inverted-value)))
        (format nil "1..~b" display-value))))

出力したものがこちらである。

出力 補足
-128 1..110000000 = (lognot 127)
128 0..010000000
127 0..01111111 = (lognot -128)
-3 1..101
0 0..00
3 0..011

- 128 + (-128) = 最上位ビット以外は0という関係になる値となっている
- 127 と (lognot 127) のビット値が、確かに反転した値とみえる

うん。満足した。これだってこれ!これだわ!そうやろ?

改善できそうな点の考察

  • format 関数への組み込み?
  • 固定桁数での表示
  • 4ビット・8ビットで区切ってほしいかな
  • 16進数への対応

ちなみに:脳内補完する方法

この際 format 関数での負の値の表現を使用し続けることにした場合の脳内での計算方法について。ビット反転による2の補数の定義を使うことができる。

  • format 関数の出力を見る
    • -10110101
  • 符号を消してビット反転する
    • 01001010
  • +1 する
    • 01001011

これで何も問題ない。

ところで、この関数を使うタイミングはいつなのか?について

Common Lisp を勉強していてありがちな現象が、「それ、XXに書いてあるよ」 である。今回遭遇した負の値の表現に関しても、その現象が起こらないかなと思う部分がある。自分で書いたコードは、自分なりには努力したが、なんだか、おさまりがすごく悪いような気がしている。感覚なのでうまく言えないのだが、、、。ただ、仕様文書にも、いくつかのキーワードでの検索結果でも見つけられなかったことから見るに、検索性の悪い話題であることは間違いない。
そもそも、この問題は実際いつ発生する問題なのか?話題にならない程度に問題のおこらない現象なのではないか?今のところ自分としての見解は、「ビット反転を使用しない限りは発生しない」 のではないかということである。

単に計算をしているときに「負の値のビット表現がほしい!」と思うだろうか?思わないと思う。そもそも16進数にせよ2進数にせよ、必要とされるのはビット演算がかかわってくる場合に限られるように思われる。
ビット演算をしているときに、負の値がふつう現れるか?基本的には現れないように思う。今自分が思いつく限り、ビット演算を必要とする計算のほとんどは、正の整数のまま処理ができるように思われる。

  • バイナリファイル、バイナリストリーム(ネットワークとか)の読み書き - ldb関数が使える
  • データに対するマスク処理、パターンマッチ - and, or, あるいは bit-vectorを用いる

ふとした瞬間に「負の値」が現れるのは、ビット反転を行ったときだけである。くどいようだがCommonLispの整数は無限に桁を持つことができ、有限桁数の値であれば正の数のまま処理ができる。and も or(ior) も、xor もだ。唯一の例外が、ビット反転を伴う計算をした時である。上位側まで無限に続く1のビットを表現するために、内部的に負の整数となる値を得ることになる。

(show-binary #b10110100)                     ;=> "0..010110100"
(show-binary (logand #b10110100 #b11110000)) ;=> "0..010110000"
(show-binary (logior #b10110100 #b11110000)) ;=> "0..011110100"
(show-binary (logxor #b10110100 #b11110000)) ;=>  "0..01000100"
(show-binary (lognot #b10110100))            ;=> "1..101001011"

回避策:ash 関数を用いたビット幅の制限

負の値を負の値のままビット演算したいという場合は、どうしても無限に続いているということを意識する必要がある。よく注意して扱えばなんとかなる。
反面、正の値のままで扱う方法もある。lognot による反転の代わりに、2の補数の計算をすることでそれができる。

(show-binary (lognot #b10110100))      ;=>  "1..101001011"
(show-binary (- (ash 1 9) #b10110100)) ;=> "0..0101001100"

できるとは書いたが、私は使わないだろうと思う。ビット幅が制限されるのも、どうにも都合が悪い。型の宣言をすれば必要なかったりしないだろうか?

終わりに

この調査を始める前に、ビット演算の方法を調査していた。その中で lognot の出力がどうにもおかしいことに気付いた。その原因は何だと調べていたら、format関数とビット値の表現方法の問題だとわかった。思った通りの表示の方法を得るために、工夫をした。大変面白い体験となった。
また、この記事の内容は、実用的にはおそらく必要性が低いと思われる。読み物として楽しんでいただければ幸いである。返事は遅くて内容もお礼だけになる気もするが、、、コメントいただければ幸いである。

CommonLisp のビット演算を調べた話

ことのあらまし

Lispの勉強用サイトとして、SBCL をサポートしているプログラミング問題サイト HackerRankを愛用している。

その挑戦の中で、ビット演算を必要とする問題があり、いざどのようにするかを調べてみたのだが、最初探し方がまずくて見つけられなかった。というか、最近真っ先に逆引きCommonLispを参照するクセをつけているのだが、探して見つからなかった。

というわけで、調べ、おおむね逆引きにまとめたのだが、整数が”無限の長さを持つ”ことによる”負の整数のビット表現”でドはまりした。やってみるとパズル的で面白いのだが、初めて使った人は同じ罠にはまらないかな、、とも思った。初心者バイバイ感あった。

というわけで、

この記事では、調べたことを逆引きに書いたよという単なる報告と、ドはまりした負の整数とビット演算の関係について別の記事 に書いたことの報告を書く。あまりに長くなったので分けた。

概要

  • CommonLispにおけるビット演算について調べた
  • 整数のビット演算をする log*系関数 を知った
    • それと等価な演算ができる boole 関数があることを知った
  • 今回は書いていない:bit-vector によるビット演算があることを知った
    • 処理は log-*系関数 で行う
    • こちらはまだ試していないのでこの記事にも逆引きにも書かない
    • ライブラリや実例のリンクだけ。
  • 本題:log* 系関数でのビット演算と負の数値について
    • あまりに長かったので次の記事にする

参照

全カットでお送りします

CommonLisp における整数値のビット演算 -> log*系関数, boole関数

logand, logior (or演算), logxor, lognotなどビット演算処理が一通りそろっている。逆引きのビット演算の項目として書いた

あと、boole 関数はlog関数と同じことを「オペレータを指定して」できる。よく見ると、boole のほうが少し処理の種類が多い。なんとなく、遺伝プログラムとか人工知能などといったプログラム生成の論理処理用に作られたのでは?と想像した。データとして演算が扱えるということで。逆引きのビット演算の項目の中に一緒に書いた。

bit-vectorを使うという選択肢 -> bit-*系関数

bit-vector についてはそこまで調べていない。

  • ビットベクターのリテラル表記は #*10110100 のように、 #* から始める
  • bit-vector 同士の演算は、bit-*系関数 を使う
    • ほぼすべての種類の演算がそろっている
    • vector なので、シーケンス関連の関数が一通り使える
  • ビットベクターと整数との相互変換を扱う標準の方法は、無いといってよい
    • coerce 関数 を使う方法があるらしいことはわかった
  • ライブラリ bit-smasher がある
    • 整数値、文字列、ビットベクタとの相互変換ライブラリ

log* 系関数でのビット演算と負の数値について

まとめというには長い記事になったので、別の記事 としてまとめた。

概要としては

  1. なんで (format t "~b" (lognot 8)) ;-> -1001 となるのだろう?
    • 自分が表示してほしい値は 1011 とか 1111 1011 なのだが?
  2. あ、整数値は無限に長いので表現が無理なのか、え?でも 1001 と 1011 ではだいぶ違うけど、、
  3. ああ、、、符号部と整数部が分かれて表示されているのか、、、
  4. これは、、仕様っぽい、、、しょうがない、ちょっと考えるか、、、

そういうわけでいろいろ考えた結果、負の整数値でもビット値として表示できる次の関数を作ってみた。

(defun show-binary (value)
  (if (>= value 0)
      (format nil "0..0~b" value)
      (let* ((sign-inverted-value (* -1 value))
             (bigger-2-power (ash 1 (+ 1 (integer-length sign-inverted-value))))
             (display-value (- bigger-2-power sign-inverted-value)))
        (format nil "1..~b" display-value))))

この関数を使った時の表現は, 正の値には 0..0 を、負の値には 1..1 を付けて表示する。
負の符号の整数値は、上位ビット側に無限に 1 のビットがあることを表現しているつもり。

value binary 補足
-128 1..11110000000 = (lognot 127)
128 0..010000000
127 0..01111111 = (lognot -128)
-3 1..11101
0 0..00
3 0..011

とはいえこの関数では

  • format 関数に統合したい
  • lognot のビット反転の値と反転前の値の桁数が現状そろわない
  • 固定桁数での表示をしたい

などいくつかの自分ニーズに応えられていないので、今後の改良が待たれる。

Written with StackEdit.
Written with ATOM

2015年11月7日土曜日

CommonLispでpackageとか名前空間とか コロン(:) について知ったこと

概要

  • Common Lisp の package について
    • 解説したリンクを集めた
    • package について説明を試みた
    • package について疑問に思ったことをまとめた

参照リンク集

CommonLispでの Packageとは?

  • Lispの関数名も変数名も シンボル として扱われることを納得しておく必要がある
    • 関数名、変数名、スペシャル関数名、マクロ名 etc
  • シンボルが 所属 する シンボルの管理単位
    • 一部の例外を除く(!)すべてのシンボルは パッケージに属している
    • 例外1:gensym で生成されたシンボルは どのパッケージにも属さない
    • 例外2:キーワード - キーワード(keyword)という 特別なパッケージに属している
  • Common Lisp の第一級オブジェクトである(後述)
  • CommonLisp が標準で持っている関数やマクロや変数(シンボル)は
    cl, common-lispという名前空間に属している
  • REPLで実行して一時的に作られた and/or
    特にパッケージを明示せず定義されたシンボルは
    cl-user, common-lisp-user という名前空間に属している
    • REPL のデフォルトの package である

シンボルは第一級オブジェクトである、とは?

なんでも定義・変更できる(?) Common Lisp の例にもれず、package も各種操作を受け付けるということ
  • パッケージ(という値)の定義、削除
  • パッケージの名前の定義、削除、変更、ニックネームの定義
    • やっぱりパッケージを表すシンボル なんだろうか。調べきっていない
  • パッケージの中身=シンボル、の追加、削除
  • パッケージの外側に公開(export)するシンボルの決定
  • 他パッケージに属するシンボルを自パッケージに包含する
  • 自他パッケージに属するシンボルを「隠す」「上書きする」
    • shadowing? ここがまだよくわかっていない、あるいは困るまで調べない
    • 関数のオーバーライドと呼ばれる機構に近いらしい
  • 現在のパッケージ を切り替える
  • 各種調査用関数

パッケージのシンボルに対するアクセス方法 … コロン(:) の意味

  • package-name:symbol-nameexport されているシンボルにアクセス
    • packageが読み込み済みである必要がある
    • ppcre:scan ql:quickload asdf:load-system など
    • あるライブラリが提供している関数を使うときはこの方法を使う
  • package-name::symbol-name で パッケージ内の任意のシンボルにアクセス
    • exportされていなくてもアクセス可能
    • private, friend, protected 、、、なんてものは存在しない、完全ノーガード
    • shadowingしたらどうなるんだろう?
    • この手段を使うのは冷静に考えて邪道

コロン(:) を使う特別なシンボル…キーワード について

  • :keyword のように、コロン(:)から始まるシンボルをキーワードという
    • 何もない名前空間を参照しているわけではなかった
  • キーワードは 評価するとシンボル自身を返す
    * :test
    
    :test
  • キーワードは、keywordパッケージに属する
    • という扱いらしい。

Common Lisp のソースを読んでいて浮かぶ疑問

  • defpackage ? in-package ? なにこれ?
    • defpackage のところに、パッケージ名が書かれています。
    • :export という項目があれば、それが公開されている 関数、変数の一覧です
    • in-package はそのあとに定義したシンボルをパッケージに所属させるための
      定型文ですので、自分でライブラリを書くのでなければ気にしなくてよいです
  • ライブラリの関数なんかは ライブラリ名 + : + 関数名、で呼べるんだね?
    • だいたいそうです。cl-ppcre:scan とか asdf:load-system とか。
    • ライブラリ名とパッケージ名が違う可能性があるので注意してください
    • ニックネームが提供されていることがかなり多いです。 cl-ppcreppcre でもOK。
  • (あるはずの関数・変数について)そんなものないって怒られるんですけど
    • asdf, quicklisp でライブラリの「処理の中身とシンボル定義」を読み込む必要があります。
      • 読み込んだ後から使えるようになります
    • 自分でパッケージを扱いだすと、もう少し複雑な「シンボルがない」状況に直面すると思います
  • defsystem, defgeneric, defmethod, def** ってちがうの?
    • defsystem はわりと関係あるんですが、、、わかってません。ひとまず ASDF に関連してます
    • defgeneric, defmethod は CLOS ですね。まだよくわかってません。
    • だいたい「**を定義するマクロ」だと思って間違いありません。

他言語から流れてきた人間として思う疑問

  • namespace, using (C++, C#, Java) とは違うの?
    • namespace はかなり package に近い、クラスや関数の所属先を決めている
    • 違いは CommonLisp では シンボルは、定義された瞬間のpackageに属する こと
    • in-package で定義される 現在のパッケージ に属する
    • シンボルをパッケージに所属させることを intern というが
      任意のパッケージを指定できる
    • using の代わりに、defpackage の :use や use-package関数を使う
  • require(ruby), import(python) とは違うの?
    • common lisp にも require はある、、、いろいろまずくて誰も使ってないけど
    • ライブラリをひとまとまりで読み込む標準の機能はない
    • それは quicklisp や asdf が手助けしてくれる
      • はよ言語標準にならんかな
    • 個別ファイルであれば load を使うことで可能
    • using の時に書いた defpackage の、、、などが、そのpackageにあるシンボルを
      パッケージ名省略して使います、という宣言になる

まとめ。他の言語がむしろ、一つの文に複数の機能を備えていると言えるのでは。

  • 名前空間の定義
  • (名前空間に属する機能の)プログラムやデータの一括読み込み機構
  • 関数名、変数名、クラス名について、名前空間の明示的な省略
そしてLisperはおもむろにマクロを定義するのであろう。

ひとこと

  • Common Lisp における package に調べだしたところ、
    それがなんであるかについてはイメージを持てたのだが、
    いざ説明を書こうとして説明が難しすぎてさじ投げた
    • 伝わる書き方というのが結局見えなくなった
    • 特に、他言語の例については、ある程度理解が進むとむしろ説明が難しい
    • 何がわかっていなかったかわからなくなる
    • 他言語の例は自分が知っている言語をさらしているだけのような気がする
  • 投げたさじを拾ってわかっていることだけまとめておいておくことにした
    • 伝わるように書くことをあきらめた
  • Quick Reference に載っている関数を一通り試したのだが、
    一部の関数が思ったように動いてくれない。使い方を勘違いしているのだろう。
Written with StackEdit.

StackEdit上の編集でXXを含む記事をBloggerに投稿する方法メモ

画像

Blogger はURLを指定して画像を記事に埋め込むことができる。StackEditはMarkdownの画像埋め込み機能を使ってそれを簡単に実現できる。
アップロードはどうせGoogleのサービスを使っているのだからGoogle+ がよいだろう。StackEdit のGUIに Google+の画像をImportしてくるというボタンもあるため、使いやすい。

アップロードテスト用の意味のない絵 タイトル
画像のをつける機能はないのである!

Markdownの記法としては

![<alt属性テキスト>](<ImageURL> "<title属性テキスト>")

Google+ の画像を使うときは、素直に StackEditの機能を使ったほうが良さそうである。URLが埋め込み専用のシンプルなものになっている。

アニメーションGIFもいける。

画像だからね。
ウゴツールで作成した特に意味のないGIF画像

2015年10月22日木曜日

Viscera Cleanup Detail 攻略 : センサー反応 そのほかtips

少しだけ:Viscera Cleanup Detailとは

怪物に襲われたゴミ処理場、何かの生物に襲われた?医療設備、何かあったらしい宇宙ステーションなどのさまざまな惨劇の舞台を清掃するゲームである。

Visceraとは臓物の意

ぶちまけられた血、反撃の後のと思われる銃痕、薬莢に銃、何よりバラバラになった人体と臓物、たおされた怪物の一部などなどのグロ要素
そこに馬鹿みたいに散りばめられた菓子の袋や紙コップ、中華料理のテイクアウト箱、缶。などの、なんで片付けねぇんだクソ、、と思わされる要素に満ち溢れた素敵なゲームである。

この記事はプレイしたことがある人を対象に書いている。ゲームの様子などはぜひ実況者さんのプレイを参照されたし。

センサーに反応するもの

センサーには二種類あることはプレイされた方であればご存知のことと思う。だが、何に反応するかは、割とわからなくなりがちであるので、まとめた。

緑のセンサー:物体反応

  • 薬莢
  • 銃痕、プラズマ銃的な攻撃の跡
  • 煤汚れ(プラズマ溶接銃や火薬ドラム破壊などで出る火の跡)
  • 菓子袋、紙コップなどゴミ
  • バケツ
  • 壊れたランタン

青のセンサー:生体反応

  • 肉片、臓物、未知の生物
  • 血液
  • バケツ

覚えておきたい

  • バケツは両方に反応
  • 銃痕、煤汚れは物体扱い
  • ドラム缶、何かの箱?ブロック?コンテナ?は清掃対象外
  • ステージごとに清掃対象外の物体は案外ある。みどりの植物体とか。

その他Tips

  • zero gravity のエレベーターは重力On時に稼働する
  • 無重力状態では、汚れたバケツをぶちまけても周りは汚れない!
    • ありがたいが、将来変更されても不思議ではない
  • バケツは水入りでも2段まで安定して重ねて運べる
    • 3つ以上はうまくいかないことが多いのでやらない
    • (追記)Shiftで歩いているときは3段安定らしい。
      • 私は3段持って走ると、段差を超えたときに大体吹っ飛ぶ。
  • 一番の敵は物理エンジンである。間違いない。
    • 特に薬莢はゴミ箱の中身をぶちまける原因になりやすい。
      薬莢を含むゴミ箱には、臓物をできるだけ入れないのがよい

ゲームについてのその他のこと

リアルタイム2時間を平気で食いつぶしてゆくゲーム。

ゲームにおける効率化の追求とミスをしない手際のよさの育成がされる(プレイヤーの。)

綺麗になった部屋を見てなんか満たされる感覚を味わえる

イラついたらプラズマ溶接銃で溶かしまくろう!

2015年10月14日水曜日

StackEditを使ってBloggerに記事を投稿する際に注意することのメモ

注意事項一覧

  • 記事名は原則としてファイル名
    • 後述の YAML Formatter を用いることでつけることが可能
  • タグはつけられない
    • 後述の YAML Formatter を用いることでつけることが可能
  • 投稿のID (PostID) は、記事編集ページのURLの中に含まれている
    • 記事を編集で開き、URLを確認する
    • 記事一覧ページで記事編集ページへのリンクURLを確認する
  • アップロード後に編集、そのあとに再アップロードすると、、、
    • タイトルは元に戻る
    • タグは元に戻る
    • 記事内容はアップロードしたものに戻される
    • とにかく全部元に戻るので、Stackedit の中で完結するようにしないといけない
  • 箇条書きは「前」と「後」の両方に空行がないとダメ
    • 「前」に空行がない場合は箇条書きと認識されない
    • 「後」に空調がない場合、箇条書きの一部とみなされ、組み入れられる

YAML Formatter によるメタ情報の記載方法

StackEditがBloggerにアップロードする場合、YAML Formatter によるメタ情報の埋め込みに対応している。記事テキストの冒頭に、次のようにメタ情報を記載する。

---
title: 記事タイトル
tags: タグ1,tag2,タグ3
---

利用可能と説明されているタグは

  • title : 記事公開用タイトル
  • tags : 記事のタグ, カンマで区切る
  • published : (未確認)
    • false で非公開状態でアップロード?
    • (追記) 2015-11-07 : false で下書き状態でアップロード。
  • date : (未確認)
    • 公開日設定をできそう
    • 公開予約もできる?

情報は2015-11-09現在。

スタイルや記事の書き方に関連する事項 (2015-11-09追記)

  • 記事タイトルと見出しレベル1を同じにしたら、同じ文章が大きく二つ並んで見苦しい
    • 見出しレベル1:#一つ, ===による区切り
    • Markdown の記事スタイルとして、見出しレベル1の要素を記事タイトルとして使う方法はとれない
  • 現在自分の 使用する Bloggerスタイルテンプレートは、見出しレベル2より、レベル3のほうが大きい。
    つまり、テンプレート次第では、見た目に影響が出てしまう。使用に注意が必要
    • できるだけ記事の論理性に一致するテンプレートを使いたいところ
    • h1 が一番目立つ、h2 が次、h3はそれより小さい、、、
    • スタイルシートのカスタマイズも手ではある

Written with StackEdit.

2015年9月26日土曜日

CommonLisp の標準機能における繰り返し処理の一覧

参考

Common Lisp Quick Reference

Land of Lisp (書籍) : 日本語訳10章にある Loopマクロ周期表が役に立つ

使用方法については次を参照。
- Lisp入門サイト(そのうちまとめる)
- Hyperspec
- 逆引きCommonLisp の 制御構造のページ

一覧

どれぐらい役割や使い方が簡単に理解でき かの順に並べている

  • dotimes, dolist
  • map系関数 : mapcar, mapc, etc…
  • xx-if, xx-if-not 系関数 : remove-if-not, substitute-if
  • loop (永久ループ)
  • do
  • loop (複雑なマクロ)
  • tagbody と go を用いたループ

これは、、、なかった

  • foreach, each : dolist, loop
  • for : 上記のうちからデータ構造に合ったものを選ぶ
  • foreach-range : OnLisp にある mapa-b など参照
  • while : do, loop で実装, 有志のマクロなども参照

補足

  • 少なくとも上を覚えておくと、ProjectEuler, HackerRank etc… などの回答系サイトでは困らない
  • 同じことを繰り返した結果、面倒になって、OnLispに載っていたマクロを使いだすこと請け合い
  • GoogleによるCL Coding Standard で半推奨的な位置にあるためか、loopマクロをよく見かける。
  • REPLのエラー表示でマクロ展開形にtagbodyが出てくることがある。マクロは自由である。
  • 実際のコードを見てどれが繰り返し処理かを見抜くことは,,,私には少なくとも難しい。
    • APIやデータ構造の把握が先に必要。
  • 書き漏れがあったらまた記事更新する
    • もっと伝わる書き方がわかったら記事更新する

書籍のご案内

Written with StackEdit.

2015年9月13日日曜日

BloggerにMarkdownで記事を書きたいんです

Blogger に Markdownで記事を書きたいんです!!楽なんです!

大切なことなので2回書いた。

StackEdit がその欲求を かなり 満たしてくれる。

特にソースが書きやすい。Blogger のソースコード対応は実際残念

(defun tarai (x y z)
  (if (< x y)
      y
      (tarai (tarai (1- x) y z)
             (tarai (1- y) z x)
             (tarai (1- z) x y))))

うまくいったらごかっさい!

覚書。

  • いきなり公開状態になるようである。要注意。
    • (追記:2015-11-10) YAML Formatter で published: falseを指定することで非公開でアップロード可能
  • タグは当然(?)つかない。つけ方あるかも。
  • 一度アップロードして、タグ付けして、再アップロードはタグに影響なし。
    • (追記:2015-09-26) タグ消えてた。YAML Formatter でつけるのが吉
    • (追記:2015-11-10) YAML Formatter でつければ付け替えも容易
  • 冷静に考えると、新しい記事としてアップロードされるわけではないのだな
    • (追記:2015-09-26) Bloggerの投稿済みページ管理からPostID を見つけ出して指定できる
    • (追記:2015-11-10) StackEdit 経由であれば自動的にID を認識して上書きしてくれる
  • なぜはてなにしなかったのかと今は思う
  • Dropbox との相互syncとあわせると記事管理がはかどる、、、ことを期待
  • markdownで改行すると、アップロードでも改行される。これは少し期待と異なるが許容範囲。

注意点をまとめた記事を書いた。

Written with StackEdit.

2015年8月26日水曜日

ASDF にかかわる右往左往

かかずにはいられない

ASDFに対する先入観がゆえに迷う

ASDFについてかつて聞いたことがあった、yum や apt-get のようなものと思っていた
そのことを知っていたがゆえに迷った。yumや apt-getで取得したプログラムがどこにおかれているか、普通は知らないようなもので、いったいどこにあるのか、ちょっと調べただけでは出てこなかった。

なお、正確には asdf-install が実際 yum や apt-get のような役割を果たしていた
現在はQuicklisp がその役割を担っている。

Quicklispは認証つきHTTP Proxy を超えられなかった。

Quicklisp 自体は Proxyなしの環境で動作することを確認した。手軽ですばらしい。

認証付のProxyについては?無理である。公式にも(今は)出来ないと書いてある。

じゃあ作ってやるぜ!と一瞬思ったが、
誰が使うんだろう?とか、自分なんかに、とか、
とりあえずやらない方向の感情が渦巻いたのでとどまった。

そんなことよりライブラリが動いてほしかった。

公式の説明にすべて書いてあった

  • ~/common-lisp フォルダ内にライブラリをフォルダごと置く
  • フォルダ名と 中にある .asd の名前が同じになるようにする
  • 大体のライブラリは .asd が提供されている
  • 自分で作ったライブラリでも同じようにできる
と書いてある。英語で。英語で。そしてすべてそのとおりにすることで結果的に動いたのであった。

公式の情報に気づいた時点で、古いasdf-install の日本語の情報にはあたったあとであり、Quicklisp は Proxyなしで普通に使う方法がわかっていたこともあってASDF についての調査がほぼ意地になっておりWindowsでは微妙に違うね、とかASDF 3.1.5 以降では、とかXDG_DATA_PATH とかわからないキーワードに引っかかってみたりなんとなくそうらしいところにフォルダをおいてみたりQuicklispのフォルダにおいてみたり環境変数を見てみたりパスを確かめる関数を探してみたりして片っ端から失敗して結果完全に頭に血が上っており要するに

本当にそうだと気づくまでに2日かかった。

SBCLの認識するホームディレクトリを確認する方法

次のコードを実行することでわかることを知った。
(truename "~")
もっとも、実行結果で偶然わかるのであって、処理自体はエラーになる。
わからないが用は足せる。というやつである。

Lispの情報の大半は英語である!

和訳情報もあるし、日本語で有用な情報を発信される方はこれが結構多い。
そして2chのLisp関連スレは意外なことに機能しているし、
困らないんじゃないか!と思ったが、これがこまる。
2chコワイ。そもそも何を聞いたらよいかわからないという。

丁寧な解説は基本的に英語であるというのは身もふたもない事実なので、
冷静に英語を読んだほうが良い結果になりやすい。と今回の件では思った。

Windows の SBCL で ASDF を使って ライブラリを読み込む

あるいは Windows でちょっと Lisp を使いたいんだけどライブラリを読み込む方法がわからないときに役立つ可能性のある記事。なお、すべてASDFの公式に書いてある手順である。

概要

Windows上のSBCLで、ASDFを使ってライブラリをREPLに読み込む方法を確かめた。

注意事項

2015現在、プロジェクトをREPLに読み込む標準的な方法は Quicklisp(https://www.quicklisp.org/beta/)です。
Quicklispに登録されているライブラリであれば、この方法を使うよりずっと楽です。

なぜ今回このようなことをするに至ったかというと、
QuickLispが認証あり HTTP Proxy を越えることが出来なかったためです。

それはそれとして、作りかけのおれおれライブラリを常用する場合などに備えて、知っておくとよい、、、かもしれません。

この記事ではやっていないこと

.sbclrc に書き込んで自動読み込み
SBCLを停止せずに再読み込み
ソースコードの置き場所を変更する

参考リンク

バージョン情報

  • 言語環境 : SBCL 1.2.13 (Windows, x64)
  • OS : Windows7, Windows8.1

重要な事柄

SBCLにはASDF が標準添付されています。
次の手順をREPLで実施することで、ASDFの機能を有効化できます。

(require 'asdf)
; あるいは
(require "asdf")

手順


  • ライブラリのソースコードをダウンロードします
  • 自分のドキュメントフォルダ (C:\Users\<ユーザー名>\Documents)を開きます
  • common-lisp フォルダを作成します
  • ソースコードを展開します。フォルダが出来ます
    • たとえば split-sequence-1.0 というフォルダ
  • フォルダの中に (ライブラリ名).asd というファイルがあることを確認します
    • これがASDFの認識するライブラリの情報ファイルです
    • ヘッダファイルのようななにか
  • common-lisp フォルダの中にソースをフォルダごと移動します
  • フォルダ名を (ライブラリ名) になるようにします
    • split-sequence のようにする
    • .asd ファイルのライブラリ名と同じである必要があります
  • SBCLを起動している場合は、一度とめる必要があります
    • とめない方法は未調査
  • REPLで ASDF を有効化(先述のとおり)
  • (asdf:load-system "(ライブラリ名)") を実行します
    • (asdf:load-system "split-sequence")
  • ライブラリの関数その他もろもろが読み込まれてライブラリが利用可能になります

感想

出来てみれば公式に書いてあったとおりであった。そうとは知らず右往左往した。

2015年8月15日土曜日

第05期のテーマはLispにしてみよう

Lisp(また)始めました

大学生のときに勢いでLispをして現実に流されたのだが、
今回は現実にさらされているので、もう流されても大丈夫

始める前から役に立たない記事ばっかり増えそうだ、、、
心構えは「恥をさらしてみよう」

問題は、ここに書かれている方法が「唯一で正しい方法だと思い込まれる」ことぐらい、、。

Lispは、今ちょっと試して調べて分かったこととしては、
ちょっとLispがわかってくるだけで3つぐらいの書き方が思いつき
そして違いは読みやすさとデータやスコープのまとめ方と速度。
速度が違いそうという気はするが、実際は?まだわからない。

なお、言語Common Lisp で、環境は SBCL (1.2.14) です。
Clojureに興味はある。だがまずは、古臭くてべたべたに書ける世界へ。初めての方には ClojureかSchemeを学ぶことを深くお勧めします。はい。

第05期の期間情報メモ

2015/08/15 開始を宣言。

その間にしていたこと
  • ドローンはあきらめた(お金)
  • ゲームをかなりしなくなった
    • とはいえFallout4 の発売まち
  • 投資は続けているが、新しいこともなし
  • vagrantとansibleと仮想化に少し詳しくなった
    • ネットに記事があふれているので書く予定なし