遅延シーケンスでfizzbuzz

ブログに書くようなマトモなネタがなく、また放置気味になってるので、仕事の辛さについ現実逃避したコードとか挙げとく。

(defn- fb
  "convert num to FizzBuzz string"
  [x]
  (let [fbstr (str (if (zero? (rem x 3)) "Fizz" "")
                   (if (zero? (rem x 5)) "Buzz" ""))]
    (if (= "" fbstr) (str x) fbstr)))

(defn fizzbuzz-seq
  "returns the seq of FizzBuzz string"
  []
  (map fb (drop 1 (range))))

(defn fizzbuzz
  "prints FizzBuzz strings at each line"
  [x]
  (doseq [s (take x (fizzbuzz-seq))] (println s)))

遅延シーケンス面白いね。

Gaucheのgit先端をコンパイルしてみた、無駄にclangで

先日thread-sleep!のバグを見つけて、報告したとたんshiroさんが一瞬で修正しててマジ感動したので次のリリースが待ちきれずgitの開発版をビルドしてみた。
あと無駄にclang使ってみてる。特に意味はない。

マニュアル読まない子なので一晩悪戦苦闘してたんだが、まとめるとほんと一瞬。

まず、Gauche最新リリース版がインストールされてないとダメっぽいのでちゃんとインストールする。これのせいでけっこうハマった。

% git clone git://gauche.git.sourceforge.net/gitroot/gauche/Gauche
% cd Gauche

MacとかBSDでもないのにclangでビルドしたいとかよくわかんない人だけ、configure.acを編集。

diff --git a/configure.ac b/configure.ac
index be6e7d6..1fe7f5d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -314,7 +314,7 @@ case $host in
     CFLAGS="$CFLAGS -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1 -D__EXTENSIONS__" ;;
 esac
 
-AC_PROG_CC
+AC_PROG_CC(clang gcc cc)
 AC_PROG_CC_STDC
 AC_C_CONST
 AC_PROG_MAKE_SET
@@ -325,7 +325,7 @@ AC_CHECK_PROGS(MAKEINFO, makeinfo)
 AC_CHECK_PROGS(GZIP_PROGRAM, gzip)
 
 dnl for cross build
-AC_CHECK_PROGS(BUILD_CC, ${build}-gcc ${build_alias}-gcc gcc cc)
+AC_CHECK_PROGS(BUILD_CC, clang ${build}-gcc ${build_alias}-gcc gcc cc)
 
 dnl Safe default CFLAGS (usually -g -O2 if you're using gcc, empty otherwise).
 dnl If the user overrides CFLAGS during configure, which is recorded.

さらに、先日自力ビルドしたclangのせいかよくわからんけど、またインクルードパスでハマって嫌な思いをしたので直しとく。

pushd .
cd /usr/include/
sudo ln asm-generic asm
popd

ここからは変にコンパイラ指定したい人も共通。autoconf普通にやるんじゃなくて、それも含めたスクリプトを叩く。ここでもすごくハマった。

% ./DIST gen
% gauche-config --reconfigure | sh
% make
% sudo make install


さて、実行してみる。

% gosh
gosh> (use gauche.threads)
#<undef>
gosh> (time (thread-sleep! 0.01))
;(time (thread-sleep! 0.01))
; real   0.010
; user   0.010
; sys    0.000
#<undef>
gosh> (time (thread-sleep! 1/100))
;(time (thread-sleep! 1/100))
; real   0.010
; user   0.000
; sys    0.000
#<undef>
gosh>

よし。ちゃんと分数でもthread-sleep!できてる。ちなみに対策されてない版だと1秒も待たずに終わります。

しかし、上手く動いてるみたいだけども0.01と1/100でuserの部分が違っちゃうのは気になるね。

Ubuntu11.4のclangでC++のコンパイルするとiostreamとかのインクルードエラーが出る件の対処まとめ

さっきの方法 は何か怖いので正しいと思える方法で対処する。
ビルドするだけなら簡単だけど、apt的に色々あると嫌なのでUbuntuらしく、むしろDebianらしく解決してみる。

dpkgの作りかたは簡単だけど、我流すぎてバージョンの扱いとかわりと雑だったのでここを参考に作法とかに従ってみた。

とりあえず必要なものをインストール。なんか必要なさそうなのもインストールしてる気がするけど気にしない。

% sudo apt-get build-dep clang
% sudo apt-get install devscripts

作業場所を作り、ソースをダウンロード。重い。

% mkdir ~/deb/clang
% cd ~/deb/clang
% apt-get source clang

作業ディレクトリに潜る。

% cd clang-2.8/debian
% debchange -i

changelogを書くことになるので、バージョンが被らないように気をつけて書く。今回はこんな感じにした。

clang (2.8-0forgcc4.5) natty; urgency=low

  * add gcc4.5 include path

 -- illness072 <illness072@yukiho>  Sat, 20 Aug 2011 23:08:03 +0900

インクルードパスがベタ書きされてる何か切ない気持ちにさせられるソースコードを編集。

% emacs clang-2.8/tools/clang/lib/Frontend/InitHeaderSearch.cpp
--- clang-2.8/tools/clang/lib/Frontend/InitHeaderSearch.cpp.orig	2011-08-20 22:57:03.556053522 +0900
+++ clang-2.8/tools/clang/lib/Frontend/InitHeaderSearch.cpp	2011-08-20 22:50:15.046053387 +0900
@@ -615,6 +615,11 @@
     // Debian based distros.
     // Note: these distros symlink /usr/include/c++/X.Y.Z -> X.Y
     //===------------------------------------------------------------------===//
+    // Ubuntu 11.04 "Natty Narwhal" -- gcc-4.5.2
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
+                                "x86_64-linux-gnu", "32", "", triple);
+    AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
+                                "i486-linux-gnu", "", "64", triple);
     // Ubuntu 10.04 LTS "Lucid Lynx" -- gcc-4.4.3
     // Ubuntu 9.10 "Karmic Koala"    -- gcc-4.4.1
     // Debian 6.0 "squeeze"          -- gcc-4.4.2

あとはビルドしてインストール。ビルドすごい時間かかる。アニメ1話ぶんじゃ済まないくらい時間かかる。

% debuild -us -uc
% cd ../..
% sudo dpkg -i clang_2.8-0forgcc4.5_amd64.deb

さっきの方法で酷いシンボリックリンク作ったのならそれは消して、さっきのHelloWorldがコンパイルできるか試す。

% clang++ hello.cpp
% ./a.out
Hello, おにいちゃん!!

よし。

clangでc++を試して四苦八苦したメモ

何の変哲もないHelloWorld。

#include <iostream>

int main()
{
    std::cout << "Hello, おにいちゃん!!" << std::endl;
    return 0;
}

こいつをclangをつかってコンパイル

# clang -xc++ hello.cpp
/tmp/cc-x0SPbV.o: In function `__cxx_global_var_init':
hello.cpp:(.text+0xc): undefined reference to `std::ios_base::Init::~Init()'
hello.cpp:(.text+0x30): undefined reference to `std::ios_base::Init::Init()'
/tmp/cc-x0SPbV.o: In function `main':
hello.cpp:(.text+0x61): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
hello.cpp:(.text+0x69): undefined reference to `std::cout'
hello.cpp:(.text+0x84): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
hello.cpp:(.text+0x90): undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))'
collect2: ld returned 1 exit status
clang: error: linker (via gcc) command failed with exit code 1 (use -v to see invocation)

まったく、君たちコンパイラはいつもそうだね。わけがわからないよ。-vを出してもインクルードパスが列挙されるばかりだというのに。それで何がわかるというんだい?
なーんて絶望しながらググってたら、どうやらgccに対するg++みたいに、clangにもclang++があると知る。

% clang++ hello.cpp
hello.cpp:1:10: fatal error: 'iostream' file not found
#include <iostream>
         ^
1 error generated.

おお、やっと理解できるエラーメッセージ。しかしまあ、iostreamが無いとか言われても知らん。
まさかほんとに無かったりする?と調べてみるも、

% g++ hello.cpp 
% ./a.out
Hello, おにいちゃん!!

ちゃんとあるじゃねえかこの野郎。
ということで今度こそインクルードパスを確認。

% clang++ -v hello.cpp
clang version 2.8 (branches/release_28)
Target: x86_64-pc-linux-gnu
Thread model: posix
 "/usr/bin/clang" -cc1 -triple x86_64-pc-linux-gnu -S -disable-free -disable-llvm-verifier -main-file-name hello.cpp -mrelocation-model static -mdisable-fp-elim -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-linker-version 2.21.0.20110216 -v -resource-dir /usr/lib/clang/2.8 -ferror-limit 19 -fmessage-length 0 -fexceptions -fgnu-runtime -fdiagnostics-show-option -o /tmp/cc-HWm9oj.s -x c++ hello.cpp
clang -cc1 version 2.8 based upon llvm 2.8rc hosted on x86_64-pc-linux-gnu
ignoring nonexistent directory "/usr/include/c++/4.4"
ignoring nonexistent directory "/usr/include/c++/4.4/x86_64-linux-gnu/"
ignoring nonexistent directory "/usr/include/c++/4.4/backward"
ignoring nonexistent directory "/usr/include/c++/4.4"
ignoring nonexistent directory "/usr/include/c++/4.4/i486-linux-gnu/64"
ignoring nonexistent directory "/usr/include/c++/4.4/backward"
ignoring nonexistent directory "/usr/include/c++/4.3"
 :
(中略)
 :
ignoring nonexistent directory "/usr/include/c++/4.3.1"
ignoring nonexistent directory "/usr/include/c++/4.3.1/x86_64-unknown-linux-gnu/"
ignoring nonexistent directory "/usr/include/c++/4.3.1/backward"
ignoring nonexistent directory "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4"
ignoring nonexistent directory "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/i686-pc-linux-gnu/"
ignoring nonexistent directory "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/backward"
ignoring nonexistent directory "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4"
 :
(中略)
 :
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.2/include/g++-v4/x86_64-pc-linux-gnu/"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.2/include/g++-v4/backward"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/x86_64-pc-linux-gnu/"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/backward"
ignoring nonexistent directory "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1"
ignoring nonexistent directory "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1/x86_64-pc-linux-gnu/"
ignoring nonexistent directory "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1/backward"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /usr/lib/clang/2.8/include
 /usr/include
End of search list.
hello.cpp:1:10: fatal error: 'iostream' file not found
#include <iostream>
         ^
1 error generated.

4.5という数字がない。とても嫌な予感。

% ls /usr/include/c++
4.5/  4.5.2@

なるほど。ということでclangのインクルードパスをどうにかしてやらないといけない。

  • Iオプションで実験。
% clang++ -I /usr/include/c++/4.5/ -I /usr/include/c++/4.5/x86_64-linux-gnu hello.cpp
% ./a.out
Hello, おにいちゃん!!

それじゃあclangにこれらのパスを通そうか・・・と思ったら、clangはインクルードパスを直書きしてるらしい。自前dpkg作ってもいいけど、わりとめんどくさい。

ということで手抜き。たぶん危険でないこともないハズなので真似するときは自己責任で。

% cd /usr/include/c++
% ln -s 4.5 4.4

・・・やっぱ後でdpkg作ろう。こわい。

ホームディレクトリに勝手に作られる日本語名のディレクトリをどうにかする

ホームディレクトリに「デスクトップ」とかいろいろと日本語名のディレクトリが作られて大層キモい。rm -rfするにもurxvt上でuim起動するとか珍しいことしないといけなくてずいぶんと気分悪かったので消してみたのだが、何かのタイミングで勝手に甦る。

ということで調べてみた。結論から言うと.config/user-dirs.dirsを編集してxdg-user-dirs-gtk-updateを走らせると良いみたい。

ぜんぶ$HOMEに設定しちまえば良いみたいだけど、~/tmpとか~/docとか作る派の人なので合わせて設定してみた。

# This file is written by xdg-user-dirs-update
# If you want to change or add directories, just edit the line you're
# interested in. All local changes will be retained on the next run
# Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped
# homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an
# absolute path. No other format is supported.
# 
XDG_DESKTOP_DIR="$HOME/tmp"
XDG_PICTURES_DIR="$HOME/doc/picture"
XDG_VIDEOS_DIR="$HOME/doc/movie"
XDG_DOWNLOAD_DIR="$HOME/tmp"
XDG_TEMPLATES_DIR="$HOME/tmp"
XDG_PUBLICSHARE_DIR="$HOME/tmp"
XDG_DOCUMENTS_DIR="$HOME/doc"
XDG_MUSIC_DIR="$HOME/doc"

設定したけど、これで何かハッピーになれるのか?わからん・・・

clangと戯れる

さいきん周囲でclang人気が高まっている気がしたので、試しにインストールして遊んでみた。

実行形式へのコンパイルは普通にgccと同じ感じで出来て、起動も普通。LLVMで動くって言ってもjavac、javaみたいな感じではないのね。
で、せっかくなので中間言語を出してみる。

clang -S -emit-llvm hoge.c

emit-llvmを抜くとなんか違うものが出る。gcc -Sで出したものに似てるし、たぶん実機向けのもの?と思い普通にgccコンパイルしてみたら出来た。どうやらemit-llvmで出来る.sファイルは実際は.sファイルではなくて.llファイルと呼ばれるものみたい。

とにかく、emit-llvmで生成されるhoge.s(hoge.ll?)ファイルはすごい読みやすい。

んでこいつを.bcコードにして、そいつを実行。

llvm-as hoge.s 
lli hoge.s.bc

gccを使って実行形式にする方法はこっち。

llc hoge.s
gcc hoge.s.s
./a.out

.sとか.s.sとか何か変だな。clang -Sで-emit-llvmの有無で拡張子とか変えてくれればいいんじゃないだろうか。まあ、-o hoge.llを付けるように心掛けるか。それとも何か俺が勘違いしてるのかな?

キーボードの設定

CtrlとCapsを入れ替えたかったが,gdmは.xinitrcを読んでくれないし,.xsessionの設定も何やら上手くいかない,起動スクリプトを読んでどうにかしようとしたが,どうも言うことを聞かない.
腹が立ったので,わりと雑な方法で変更した.他人に勧められる方法ではないので,いつか直す.

コンソールでのCtrl,Caps入れ替え

rc.localに直接loadkeysを仕込むとか怖いけど自分しか使わないのでとりあえず問題ない.ここを参考にした.

etc/rc.localを以下のように編集.

--- rc.local.orig       2011-08-13 22:51:32.195287055 +0900
+++ rc.local    2011-08-13 22:51:17.347867052 +0900
@@ -10,4 +10,5 @@
 # bits.
 #
 # By default this script does nothing.
+dumpkeys | sed -e 's/CtrlL_Lock/Control/' | loadkeys
 exit 0

X環境でのCtrl,Caps入れ替え

デフォルトのWMを使うと,.xmodmapを勝手に見つけて設定しますか?とか聞いてくれるわけだが,xmonadで同じことは当然期待できない.起動スクリプトを色々読んだがわからんのでここを参考に設定.これもなかなか香ばしいのでいつか直す.

/etc/gdm/Init/Defaultを以下のように編集.

--- Default.orig        2011-08-13 22:51:07.963177049 +0900
+++ Default     2011-08-13 22:50:47.042722044 +0900
@@ -92,4 +92,5 @@
     fi
   fi
 fi
+setxkbmap -option ctrl:nocaps
 exit 0