goshでのマクロ展開

Gaucheではマクロ展開後のコードを見るためにmacroexpandという手続きが用意されているが、マクロの使用がcar部に来ていないと展開されない。

例えば、よく例として挙げられるorマクロは


(define-syntax or
(syntax-rules ()
((or) #f)
((or exp) exp)
((or exp1 exp2 ...)
(let ((tmp exp1))
(if tmp
tmp
(or exp2 ...))))))

3つ目のパターンでは再帰的にorが登場するが、そこまではmacroexpandで展開は出来ないので全体の様子を見る事ができない。

なので、マクロの使用が完全に無くなるまで展開を続ける手続きを書いた。


(use srfi-1)
(define evalMacroDef ;macro定義を見つけたらそれをevalする。
(let ((macroName '())) ;定義があればその名前をここに格納していく。
(lambda (schemeCode)
(if (pair? schemeCode)
(if (eq? (car schemeCode) 'define-syntax)
(begin
(eval schemeCode (interaction-environment))
(set! macroName (alist-cons (cadr schemeCode) schemeCode macroName)))
(if (assoc (car schemeCode) macroName) ;macroNameの中に入っているマクロだったとき展開する
(begin
(set! schemeCode (apply macroexpand (list schemeCode)))
(if (pair? schemeCode)
(cons
(evalMacroDef (car schemeCode))
(evalMacroDef (cdr schemeCode)))
schemeCode))
(cons
(evalMacroDef (car schemeCode))
(evalMacroDef (cdr schemeCode))))))
schemeCode)))

うーん,もっと綺麗に書きたい.

これを次のように使う


(define code
'(begin
(define-syntax or
(syntax-rules ()
((or) #f)
((or exp) exp)
((or exp1 exp2 ...)
(let ((tmp exp1))
(if tmp
tmp
(or exp2 ...))))))
(or 1 2 3 4 5 6)))
(evalMacroDef code)

出力結果


gosh> evaluated (define-syntax or (syntax-rules () ((or) #f) ((or exp) exp) ((or exp1 exp2 ...) (let ((tmp exp1)) (if tmp tmp (or exp2 ...))))))
(begin #<undef> (#<identifier user#let> ((#0=#<identifier user#tmp> 1))
  (#<identifier user#if> #0# #0# (#<identifier user#let> ((#1=#<identifier user#tmp> 2))
    (#<identifier user#if> #1# #1# (#<identifier user#let> ((#2=#<identifier user#tmp> 3))
      (#<identifier user#if> #2# #2# (#<identifier user#let> ((#3=#<identifier user#tmp> 4))
        (#<identifier user#if> #3# #3# (#<identifier user#let> ((#4=#<identifier user#tmp> 5))
          (#<identifier user#if> #4# #4# 6)))))))))))

emacsのカーソル速度変更

MacでCarbon Emacsを使っているのですが、カーソル速度が遅くてかなり不便な思いをしていました。

elispで書けるのかなぁ、と思って解決策を色々探していたけど、見つかりませんでした。

そこでキー入力自体を速めてしまえばいいだろうと言う結論に達し、KeyRemap4MacBookをダウンロードしました。

ダウンロードしてインストール後、再起動するとシステム環境設定からKeyRemap4MacBookという項目が選べるようになっているので、そこの [Key Repeat]Waitの値を変更してやればOKです。

初期値が30で既にインストールした時点で、インストール前よりも速くなっている印象です。

ロベールのC++入門講座 その1

ロベールのC++入門講座

ロベールのC++入門講座

将来への不安から今年中にロベールのC++入門講座を読んどこうと思った。

分からなかったこと等のメモとしてここを使っていこうと思う。

最初の方は知っていることが多いので飛ばし気味。

これは知らなかった。includeの話。

P129

ファイル名を< >で囲めば設定されたフォルダの、” “で囲めば今のフォルダのファイルを優先的に調べる。

emacs23で新しいファイルを開いた時にemacsを複数起動させない

emacsを23にアップデートしてから、新しいファイルをFinderとかから選んでemacsで開こうとすると、もう一つemacsが起動してしまい、癖でC-x C-cをしてしまい最初から開いていたemacsも一緒に閉じてしまうという事が頻発していました。

解決方法: .emacsに以下を追加


;;複数ウィンドウを開かないようにする
(setq ns-pop-up-frames nil)

すると、常に同じemacsでファイルを開く事ができます。

エンジニアとしての生き方 IT技術者たちよ、世界へ出よう!

エンジニアとしての生き方  IT技術者たちよ、世界へ出よう! (インプレス選書)

エンジニアとしての生き方  IT技術者たちよ、世界へ出よう! (インプレス選書)

副題でもある「IT技術者たちよ、世界へ出よう!」というのは、常々自分が理想として考えていることでもある。

そういった意味で、新年の自戒を込めて読んでみようと思ったが、結論から言ってとてもいい刺激を受けたと思う。

そしてこのブログ記事を書こうと思ったのも、もちろん本書の影響を受けてである。

自分がエンジニアとしていかに生きて行くべきかと考えたときに、著者は世界へ出る準備をすることを勧める。

もはや数多くの人達が述べていることだが、「これまでの常識であった「(日本の)一流大学に入って一部上場の大企業に就職さえすれば一生安心」という考えが時代遅れであることを強く認識した上で、もっと幅広く視野を持って、自分の活躍する場を求めること」が大事である。

その上で必要となるのは柔軟な頭と、英語力であると筆者は述べる。

いまは、日本企業は終身雇用・年功序列に支えられてきたが、これからの時代はそう簡単にいかないのは多くの人が考えている通りであろう。

例えばインドのインフォシスの例が載っていたが、今後はまさに「インドのことを「単に値段が安いだけの外注先」と見下していると痛い目にあう」だろう。

日本の企業が本気で国際競争力を高めたいのならば、もっと自由に人を解雇できるようにしなければならないと著者は述べる。

私としても、人材の流動性は高めるべきだと思うし、今働いている会社に後何年いるかということも分からない。ましてや定年まで働いている姿などもちろん想像できない。

また、仕事を選ぶ際にも、「頼まれなくても自分から喜んで残業するほど楽しい仕事か」どうかで選ぶべき、という基準を著者は述べている。

これはなかなか見つけるのが難しいが、この一年はそれを見極めることに使えればと思う。

著者が薦める本

頭の体操 BEST

頭の体操 BEST

頭の体操BEST 2

頭の体操BEST 2

これは小学校の時に昔の版だが読みあさった。久々に解いてみようかな?

エンジニア30歳定年説(これが正しかったら入社したばかりだが、わたしは後数年で定年だw)のバカらしさが分かるらしいので読む。

古典力学の形成―ニュートンからラグランジュへ

古典力学の形成―ニュートンからラグランジュへ

暇があれば

いろんな人が勧めているので気になっていたが読もう。

MozReplを使ってホッテントリをすべて開く

僕が毎日見るwebページの一つにはてなブックマークのホッテントリがあります。

技術者の人たちが多いので有意義な情報が多いです。

しかし、自分が面白そうと思った記事ばかり読んでいても興味の範囲が広がらないと思います。せめてチラリとでも記事を眺めておいたほうがいいかもしれない、そう思ってホッテントリをすべて開くプログラムを作りました。

使ったものはrubyのMechanizeと、MozReplというFirefoxのアドオンです。


# -*- coding: utf-8 -*-
require 'rubygems'
require 'mechanize'
require 'kconv'
require 'net/telnet'


def mozrepl_open
$telnet = Net::Telnet.new("Host" => "localhost", "Port" => 4242, "Prompt" => /repl> z/n)
end
def mozrepl_cmd(str)
$telnet.cmd(str)
sleep(0.5)
end
def mozrepl_close
$telnet.puts("repl.quit()")
$telnet.close
end

agent = Mechanize.new
agent.get('http://b.hatena.ne.jp/hotentry')

mozrepl_open
agent.page.search('blockquote').each do |p|
p.search('cite').each do |q|
puts q.values
end
mozrepl_cmd("gBrowser.selectedTab = gBrowser.addTab()")
mozrepl_cmd("content.location.href = " + p.values.to_s)
puts p.values
puts '---'
end
mozrepl_close

実行後はこんな感じにタブがいっぱいに。

f:id:hiroshi128:20110819142019p:image

とても重いです。。。

Cの配列アクセス豆知識

この本を最近読んでます。

C言語ポインタ完全制覇 (標準プログラマーズライブラリ)

C言語ポインタ完全制覇 (標準プログラマーズライブラリ)

この中で、


array[1]

と、


1[array]

が全く同じだということを知って衝撃を受けた。

これは結局のところ、


array[1]


*(array + 1)

のシンタックスシュガーであるからなんですね。

デーモン君のソース探検 その1

買ってみた。

VMWare上のUbuntuで進めていきます。

まずはNetBSDのソースコードを取得します。がしかし、cvs loginができずに書いてあるとおりには進めないので、普通にFTPでNetBSDのソースコードを取得してきた。

取ってきたバージョンは5.1で、本は1.6を使っているけど基本的なコマンドのソースは同じだろうという判断で進めていきます。

ちなみにlocateコマンドのデータベース作成ですが、


# sh /etc/weekly

はUbuntuでは無いようなので、


# sudo updatedb

でデータベースをアップデートできます。