ときどきの雑記帖 払暁編

最新ページへのリンク
目次ページへのリンク

一つ前へ 2011年6月(下旬)
一つ後へ 2011年7月(中旬)

ホームへ

2011年07月10日

■_

勉強会が多すぎる。ってな話を昨日のTAPL読書会後の二次会で話してたり。 まあうれしい悲鳴というか贅沢な悩みなんでしょうけど。

・ひとつ書いておこう
コンピュータープログラミング入門以前
一通り読んでみて、参考文献が全然挙げられてないのが気になりました。 ページ数の都合かもしれないけど、あれだけの範囲を収めておいて 参考文献なしってのは信じがたいものがあるんですけど… 実際、前に書いたように正規表現のところに間違いであろう記述もありましたし、 書き写すとかそういうことでなく裏を取るとか確認するとかで必要だと思います (読者が、ではなく筆者が)>参考文献 これでもうこの本について書くことはないかな。 書けという圧力もなかったしw

■_ 祭り

TAKESAKO @ Yet another Cybozu Labs: Shibuya.pm#16「夏の正規表現祭り」開催しました で、スペシャルゲストとして招かれて発表謎してまいりました。 竹迫さんからメールをいただいたときはうれしかったのですが、 正直なところを書くと、どう返事をものかたいへん悩みました(笑) 何を話せばいいのかというのがあったのと、 ほかの発表者の顔ぶれを見てどういうスライド作ればいいのかと 頭抱えてしまったからです。

はっきりいって見た目の派手な、あるいは難解な正規表現をばーんと出して これは~とやるのは柄ではないしそもそもそんな必殺技を持っていない。 拡張を駆使してひとつの正規表現ひとつのコマンドで仕上げるよりも、 単純なものを組み合わせてやる方が好きだし気楽にできるのですね (そりゃあそうした方がよければ再帰的記述でも何でもやりますがw)。

とはいえ、あの会場に来る客層を考えるとそういう地味なのは受けがよろしくないだろう ということで悩んだ結果があれです。 もうちょっとなんとかならんかったのかと思うところもありますが、 今はあれが精一杯ということでひとつ。


  Togetter - 「Shibuya Perl Mongersテクニカルトーク#16「夏の正規表現祭り」」
http://togetter.com/li/159579

多少は面白がってくれた人もいたようでほっと一息。

■_

■_

昨日の volatile ネタが某IRCで話題の種になっていた模様。 ささださんによると以前からの懸案事項でもあったらしい。 ruby-dev とかで volatile くっつけたパッチをそれなりに見かけるなあとは思ってたんですが (って同じ原因や症状とは限りませんけど)。

■_ やっぱ

偽サマータイムに合わせるのちょー苦痛。

2011年07月09日

■_

月に一度。といいつつ先月はなかったし来月もないことが確定している某読書会。 まとめを書いている余裕が以下略。

■_

■_ !!~

語彙と作品 - mooz deceives you 経由 刺身☆ブーメランのはてなダイアリー で。

詳しくは元記事を読んでいただくとして、


**
* contains returns a boolean for if substr is found within str.
*/
function contains( str, substr ) {
    return !!~('' + str).indexOf(substr);
}

という記述がとあるライブラリにあったけど、これは


function contains( str, substr ) {
    return str.indexOf(substr) !== -1;
}

のように書くべきではないか等々。それはさておき。

!! はまあそこそこ見てきたイディオム(言語が違うけど)かなあとは思うけど、 そこにさらに ~ を組み合わせると。まあよく思いつくものだなあ(笑)

!! は 0 を 0、0以外を1にするテクニック。 で、二の補数限定になるけど、!! と ~ を組み合わせることによって、 -1 を 0 に、それ以外を 1 にしている。

■_ Haskell

やっぱり向こうでもHaskellはハードルが高いのかねえ。などと。

functional programming - Hard Time Learning Haskell - Programmers - Stack Exchange

Just to give a quick background I'm 18 years old, going to college this fall, started 
programming when I was in middle school. I made the decision to hold up on development 
for one of my Web projects and dive into Haskell programming. I have a few years of 
programming experience but I have never touched functional programming before.

I started with the Real World Haskell book, but after a few chapters it got too 
confusing so I stopped. Then I found Learn You a Haskell For Great Good and it went 
much better. Right now I'm on chapter 9 on the Input/Output chapter which teaches me 
about files, streams and command line arguments. The concepts are sinking in alright, 
but there's just one problem.

For every single other programming language I've learned in the past, I was able to 
make useful, working programs in at most a week after learning about the language. But 
not for Haskell. Yes I understand what types and type classes are, how to create my 
own functions and I have a decent grasp of the syntax, but I'm just not sure where to 
begin. When I want to make something useful, I have to stick everything into a 
"do" statement and then afterwards I just get stuck and don't know how to 
proceed.

How would you guys recommend I solve this problem? Do you think I should finish up my 
current chapter then spend more time writing programs rather than reading books? What 
kind of programs should I write given my current experience (again, 1 week) with 
Haskell? What kind of resources are available for me besides online books?

Thanks.

When I started learning Haskell, I was at a point where I became proficient in ruby in 
about 5 hours. Haskell took about 6 months before I felt it start to "flow". 
Don't worry, your ego is fine :-)


    For every single other programming language I've learned in the past, I was able to
    make useful, working programs in at most a week after learning about the language. 
    But not for Haskell. (...) I have to stick everything into a "do" statement 
    and then afterwards I just get stuck and don't know how to proceed.

First, let me reassure you that learning Haskell does tend to have more up-front 
difficulty than other languages. It's not really harder overall, just sooner. If 
anything, based on my own experiences, I'd say that once you reach some level of 
comfort it's actually easier to keep learning more about Haskell compared to other 
languages.

Less generally, if you have some code that seems clumsy and you're not sure how to 
proceed with a well-defined goal, then... ask for advice! Either here, or elsewhere. 
Just say "I'm learning Haskell, I'm trying to accomplish ---- , I've got this 
code so far: (...), but I can't figure out why --- doesn't work well/how to make it 
also do ---/etc.".

    How would you guys recommend I solve this problem? Do you think I should finish up my
    current chapter then spend more time writing programs rather than reading books? What
    kind of programs should I write given my current experience (again, 1 week) with
    Haskell? What kind of resources are available for me besides online books?

The biggest resources I'm aware of are:

    * Various blogs and such from people connected to Haskell one way or another
    * /r/haskell on Reddit
    * #haskell on the FreeNode IRC network
    * The various mailing lists
    * The [haskell] tag on SO, of course :]

Regarding what you should do, I'd always advise spending time writing code if you can 
do so. You may not have much success, but hitting stumbling blocks or tricky spots in 
actual code is a great starting point to guide your directions in learning. Just 
reading a book is one thing, but reading with a purpose can be much more effective. I 
wouldn't suggest dropping LYAH and such completely, though, just mixing in more 
exploratory/experimental coding alongside the reading.

Finally, for what kind of programs you should write, well... what would you do at this 
point in learning any other language? What kind of programs do you want to write? Just 
pick something that you'd enjoy, then figure out how to do it. Again, having a 
specific purpose can be very helpful. And if you don't know where to start on what you 
have in mind, that's where the community resources above come in handy. People are 
usually more than happy to help (just beware of people spinning off into really arcane 
abstractions--that's a recreational activity that Haskell enthusiasts tend to enjoy, 
but not something you need to take seriously, so don't worry if you don't know what a 
zygohistomorphic prepromorphism is).
    For every single other programming language I've learned in the past, I was able to
    make useful, working programs in at most a week after learning about the language.

What makes Haskell so hard then?

    * The purity/type-system implicitly encourages you to trundle through the design space of
      your shiny program before you even build it.

    * The static guarantees Haskell provides at the language-level are greatly debilitating
      if not properly understood.

    * most other languages are not nearly as expressive and succinct.

    * Haskell's libraries boast tons of abstractions, many of which actually get used and
      therefore need to be learnt. Before you know it, you'll be knee-deep in Monad Transformer
      stacks, slinging parallel Arrows and using <$> all over the place.

If I was to make a bad analogy, I'd liken learning Haskell to giving up nearly all 
worldly pleasures, moving to Dengfeng and joining the Shaolin Monastry, as opposed to, 
well, ringing up the nearest dojo and settling for some 40-year old american 
instructor. You'll learn similar skills at both, but some would say that your 
world-outlook, overall skill and ability will turn out vastly different, not to say 
anything of the difficulty each path will give you.

    How would you guys recommend I solve this problem?

Just two things:

    * read lots of code and then
    * write lots of code.

There is no silver bullet. Programming is hard. Most languages may hide that from you, 
but not Haskell. In fact, some would say that precisely because Haskell makes everything
explicit, programming in Haskell is easier then just about every other language.

Some things you could immediately do:

    * Read through (and modify!) a mature project like LambdaHack, which is a rogue-like
      game that boasts high-quality code. If you can understand how LambdaHack works, you'll
      have a great starting point for any of your own projects.
    * Finish Real World Haskell (an excellent book).
    * Make friends with someone who knows Haskell.
    * Join the the haskell-beginners mailing list, and ask questions on it.
    * Join the Haskell IRC channel (#haskell on freenode) and ask questions. many of them.
      stupid ones even.
    * Pick a small project and see it through. Once you have it working, ask somebody to do
      a code review. Learn from it.

Knowing the syntax of the language is a very different affair from understanding a 
complex system written in it, and exercises like these would give you an outlook that 
would be useful moving forward.

We've all been where you are right now, (to be honest, most days I wake up and I'm 
still there) and all I can say is that I wish I'd stumbled across Peter Norvig's 
excellent Teach yourself Programming in Ten Years sooner. He can answer the driving 
force behind your question far better than I ever could.

Haskell の IRC ってのはいけがみさんも以前薦めていたような覚えが。 Real Wrold Haskell を最後まで読め。か。うむむ (途中までで止まってまーす)。

■_

2011年07月08日

■_

偽サマータイム一週間経過。 つーか一時間前倒しきつい。体感としてはもっと進めている感じがあって、 「時間がねー」感がさらに強くなったというか。 夜寝る前にやってたことが、朝早起きしてできるとは限らないものねえ。

■_ ヤ・ク・ソ・ク

この volatile 問題はもうちょっとすっきり解決できないもんでしょうかねえ。

The Broken Promises of MRI/REE/YARV at time to bleed by Joe Damato

The Broken Promises of MRI/REE/YARV

tl;dr
This post is going to explain a serious design flaw of the object system used in MRI/REE/YARV.
This flaw causes seemingly random segfaults and other hard to track corruption. One popular
incarnation of this bug is the “rake aborted! not in gzip format.”

theme song
This blog post was inspired by one of my favorite Papoose verses. If you don't listen to this
while reading, you probably won't understand what I'm talking about: get in the zone.

 rake aborted! not in gzip format
 [BUG] Segmentation fault

If you've seen either of these error messages you are hitting a fundamental flaw of the
object model in MRI/YARV. An example of a fix for a single instance of this bug can be seen
in this patch. Let's examine this specific patch so that we can gain some understanding of
the general case.
FACT: What you are about to read is absolutely not a compiler bug.

A small, but important piece of background information
小さいけれども重要な、背景となる情報

The amd64 ABI*1 states that some registers are caller saved, while others are callee saved.
In particular, the register rax is caller saved. The callee will overwrite the value in
this register to store its return value for the caller so if the caller cares about what
is stored in this register, it must be copied prior to a function call.

amd64 は一部のレジスターが callee saved であるけれども、その他のものは caller saved であると
宣言しています。特に、rax レジスターは caller saved になっています。
callee はこのレジスターに格納されている値を戻り値を caller に返すために overwrite します。
したがって、caller はこのレジスターに何が収められているか注意しなければならないし
関数呼び出しに先だってコピーしておかなければなりません。

stare into the abyss part 1
the abyss (奈落の底) への階梯 パート1

Let's look at the C code for gzfile_read_raw_ensure WITHOUT the fix from above:

 #define zstream_append_input2(z,v)\
     zstream_append_input((z), (Bytef*)RSTRING_PTR(v), RSTRING_LEN(v))

 static int
 gzfile_read_raw_ensure(struct gzfile *gz, int size)
 {
     VALUE str;

     while (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size) {
         str = gzfile_read_raw(gz);
         if (NIL_P(str)) return Qfalse;
         zstream_append_input2(&gz->z, str);
     }
     return Qtrue;
 }

It looks relatively sane at first glance, but to understand this bug we'll need to examine
the assembly generated for this thing. I'm going to rearrange the assembly a bit to make it
easier to follow and add few comments a long the way.

一見これは単純なものに見えますが、このバグを理解するためには
このコードから生成されたアセンブリ言語のコードを確かめなければなりません。
追いかけやすくするためにアセンブリ言語を rearrange し、またコメントを追加します。

First, the code begins by setting the stage:

 push   %rbp
 movslq %esi,%rbp    # sign extend "size" into rbp
 push   %rbx
 mov    %rdi,%rbx    # rbx = gz
 sub    $0x8,%rsp    # make room on the stack for "str"

The above is pretty basic. It is your typical amd64 prologue. After things are all setup,
it is time to enter into the while loop in the C code above:

これはとても基本的なもので、典型的な amd64 の prologue です。
セットアップが完了したあと、上記のCコードにある while ループへ入ります:

 jmp    1180  # JUMP IN to the loop

Next comes the NIL_P(gz->z.input) portion of the while-loop condition:

 mov    0x18(%rbx),%rax    # rax = gz->z.input
 cmp    $0x4,%rax          # in Ruby, nil is represented as 4.
 je     1190 [gzfile_read_raw_ensure+0x30]  # if gz->z.input is nil, enter the loop

Now the RSTRING_LEN(gz->z.input) < size portion:

 cmp    %rbp,0x10(%rax)        # compare size and gz->z.input->len
 jge    11b0 [gzfile_read_raw_ensure+0x50]  # jump out of loop
                                            # if  gz->z.input->len is >= size

Next comes the call to gzfile_read_raw and the NIL_P(str) check. If this check fails,
the code just falls through and exits the loop:

次にくるのが gzfile_read_raw とそして NIL_P(str) 検査です。
この検査で失敗すれば、コードは falls through してループを抜けます:

 mov    %rbx,%rdi            # rdi = gz, rdi holds the first argument to a function.
 callq  1090 [gzfile_read_raw]  # call gzfile_read_raw
 cmp    $0x4,%rax   # compare return value (%rax) to nil
 jne    1170 [gzfile_read_raw_ensure+0x10] # if it is NOT nil jump to the good stuff

The return value of gzfile_read_raw_ensure (an address of a ruby object) is stored in rax.

gzfile_read_raw_ensure の戻り値 (ある ruby オブジェクトのアドレス) が rax に格納されます。

And finally, the good stuff. The call to zstream_append_input:

 mov    0x10(%rax),%rdx # RSTRING_LEN(v) as 3rd arg
 mov    0x18(%rax),%rsi # RSTRING_PTR(v) as 2nd arg
 mov    %rbx,%rdi       # set gz->z as the 1st arg
 callq  10e0 [zstream_append_input]  # let it rip

Note that the arguments to zstream_append_input are moved into registers by offsetting
from rax and that when the call to zstream_append occurs, the ruby object returned from
gzfile_read_raw_ensure is still stored in rax and not written to it's slot on the stack
because the extra write is unnecessary.

zstream_append の呼び出しが起きたときに zstream_append_input に対する引数が rax に対する
オフセットから幾つかのレジスターに移動していますが、extra write は不要なので
gzfile_read_raw_ensure から返された ruby オブジェクトは rax に格納されたままで、
スタック上のスロットに書き戻されていないことに注意してください。

stare into the abyss part 2
the abyss (奈落の底) への階梯 パート1

Aright, so the patch changes the zstream_append_input2 macro to this:

#define zstream_append_input2(z,v)\
   RB_GC_GUARD(v),\
   zstream_append_input((z), (Bytef*)RSTRING_PTR(v), RSTRING_LEN(v))

And, RB_GC_GUARD is defined as:

#define RB_GC_GUARD_PTR(ptr) \
   __extension__ ({volatile VALUE *rb_gc_guarded_ptr = (ptr); rb_gc_guarded_ptr;})

#define RB_GC_GUARD(v) (*RB_GC_GUARD_PTR(&(v)))

That code is just a hack to mark the memory location holding v with the volatile type
qualifier. This tells the compiler that memory backing v acts in ways that the compiler
is too stupid to understand, so the compiler must ensure that reads and writes to this
location are not optimized out.

このコードは、volatile type qualifier で v を保持している memory localtion に
印をつけるちょっとしたハックです。
これはコンパイラーが状況を把握するのにはあまりにもおバカ (stupid) であるので
コンパイラーに memory backing v するように指示し、
コンパイラーはその location への読み書きを最適化しないことを保証します。

A common usage of this qualifier is for memory mapped registers. Reads from memory mapped
registers should not be optimized away since a hardware device may update the value stored
at that location. The compiler wouldn't know when these updates could happen so it must
make sure to re-read the value from this memory location when it is needed. Similarly,
writes to memory mapped registers may modify the state of a hardware device and should not
be optimized away.

この qualifier の common usage はメモリーにマップされたレジスターに対するものです。
メモリーにマップされたレジスターからの読み出しは最適化すべきではありません
なぜならハードウェアデバイスはその場所格納されている値を更新しているかもしれないからです・
コンパイラーはそういった更新がいつ起こるのかがわかりませんから、
その値が必要になるたびごとにメモリーから値を読みなおさなければなりません。
同様に、メモリーにマップされたレジスターに対する書き込みも
ハードウェアデバイスの状態を変更する可能性があるので
最適化すべきものではありません。

Most of the code generated with the patch applied is the same as without except for a few
slight differences before zstream_append_input is called. Let's take a look:

このパッチを適用コードから生成されたものはパッチをしていないものと大部分が同じものなのですが、
zstream_append_input が呼び出される前のところにわずかですがはっきりとした違いがあります。
では見てみましょう: 

 mov    %rax,-0x18(%rbp)             # write str to the stack
 mov    -0x18(%rbp),%rax             # read the value in str back to rax
 mov    0x10(%rcx),%rdx              # RSTRING_LEN(v)
 mov    0x18(%rcx),%rsi              # RSTRING_PTR(v)
 mov    %rbx,%rdi                    # z
 callq  1f60 [_zstream_append_input]

The key difference is that the return value of gz_file_read_raw is written back to it's
memory location (which, in this case, happens to be on the stack and is called str).

鍵となる違いは、gz_file_read_raw の戻り値が対応するメモリ位置
(このケースでは、スタック上に存在している str という名前のもの)
に書き戻されているという点です。

the bug

The bug is triggered because:
今回のバグは次のようにして引き起こされます:

1. The address of the ruby object str is stored in a caller saved register, rax.

   ruby object str のアドレスは caller saved register の rax に格納されている

2. The callee (zstream_append_input) does not save the value of rax (it is not required to)
   and rax is overwritten in the function, leaving no references to the ruby object returned
   by gzfile_read_raw.

   callee である zstream_append_input は rax にある値を保存せず (なぜならそうすることを要求さ
   れていないから)、関数の中で rax は上書きされてしまって gzfile_read_raw が返した
   ruby object へのリファレンスがなくなる

3. The callee (zstream_append_input) eventually calls rb_newobj. rb_newobj may trigger a
   GC run, if there are no available objects on the freelist.

   callee (zstream_append_input) が eventually に rb_newobj を呼び出すが、
   フリーリスト上にオブジェクトを置く余裕がなければ
   rb_newobj が GC の実行を引き起こす可能性がある。

4. The GC run finds the object returned by gzfile_read_raw but sees no references to it
   and frees the memory associated with it.

   GC は gzfile_read_raw が返したオブジェクトを見つけだすが、それを参照しているものがないので
   オブジェクトに結び付けられているメモリーを解放してしまう。

5. The freed object is used as it were it were valid, and memory corruption occurs causing
   the VM to explode.

   それが vaild であったかのように解放されたオブジェクトが使われて、そして memory corruption
   が VM を explode する

The patch prevents this bug from happening because:
パッチはこのバグの発生を防止しますが、それは

1. The address of the ruby object str is stored in a caller saved register, rax.
   ruby オブジェクト str のアドレスは caller saved のレジスター rax に保存されている

2. The volatile type qualifier causes the compiler to generate code which writes the return
   value back into it's memory location on the stack.

   volatile type qualifier はコンパイラーに戻り値をスタック上の memory location に
   書き戻すコードを生成させます。

3. The callee (zstream_append_input) eventually calls rb_newobj. rb_newobj may trigger a GC
   run, if there are no available objects on the freelist.

4. The GC run finds the object returned by gzfile_read_raw and finds a reference to it
   and therefore does not free it.

5. Everyone is happy.
   皆が幸せになる

The general case

Given valid C code, gcc will generate machine instructions that correctly do what you want.
Of course, there are bugs in gcc just like any other piece of software. The problem in this
case is not gcc. The problem is that the object and garbage collection implementations in
REE/MRI/YARV are not valid C code, so it is not possible for gcc to generate machine
instructions that do the right thing. In other words, Ruby's object and GC implementations
are breaking their contract with gcc.

valid な C のコードを与えれば、gcc はあなたが望んでいることを正しく行う機械命令群を生成するでしょう。
問題なのは、REE/MRI/YARV におけるオブジェクトとガーベジコレクションの実装が vaild な Cのコード
でなく、gcc が正しく処理を行うための機械語命令を生成できない可能性があるということです。
言い換えると、Ruby のオブジェクトおよび GC の実装は、gcc との契約を破っているのです。


The end result is the need for shit like RB_GC_GUARD in REE/MRI/YARV and also in Ruby gems
to selectively paper over valid gcc optimizations. Having an API that might cause the Ruby
VM to fucking explode unless you proactively mark things with RB_GC_GUARD is not on the path
of least resistance toward building a maintainable, safe, and performant system. Very few
people out there know that the volatile type qualifier exists, let alone what it does.
Essentially, this means that authors of Ruby gems must understand how GC works in the VM to
prevent their gems from causing GC to break the universe.

The end result is the need for shit like RB_GC_GUARD in REE/MRI/YARV and also in Ruby gems
to selectively paper over valid gcc optimizations.
Having an API that might cause the Ruby VM to fucking explode unless you proactively mark things with RB_GC_GUARD is not on the path
of least resistance toward building a maintainable, safe, and performant system.
Very few people out there know that the volatile type qualifier exists,
let alone what it does.
Essentially,
this means that authors of Ruby gems must understand how GC works in the VM
to prevent their gems from causing GC to break the universe.



That is fucking beyond stupid.

How to detect this bug class
この種のバグの見つけ方

This could be detected by building a simple static analysis tool. You won't catch 100% of
cases, and you will definitely have false positives, but it is better than nothing.
Something like this should work:

1. Build a call digraph of the VM and/or the set of gems you care about.

2. Find all paths leading to the rb_newobj sink.

3. Find all paths which call rb_newobj, but do not save rax prior to making another
function call which is also on a path to rb_newobj.

4. The functions found are very likely to be causing corruption. A human will need to examine
the found cases to weed out false positives and to fix the code.

If you have found yourself wondering who the fuck would write such a test? it is important
for you to note that rtld in Linux does not save the SSE registers (which are supposed to
be caller saved) prior to entering the fixup function, however to ensure that such an
optimization does not cause the fucking universe to come crashing down, a test ships with
the code to run objdump after building the binary. The objdump output is then grepped for
any instructions which might modify the SSE registers. As long as no one touches the SSE
registers, there is no need to save and restore them.

If Ruby's object and GC subsystems want to prevent the universe from exploding, it must
supply an equivalent test to ensure that corruption is impossible.

もしRubyのオブジェクトやGCサブシステムが宇宙を破壊から防ぐことを望むなら、
#もうちと日本語的な言い回しにしたい
corruption (≒メモリ破壊)が不可能であることを保証するための equivalent test を
提供しなければなりません。

Conclusion
結論

MRI/YARV/REE are inherently fatally flawed.
I'm never writing another Ruby-related blog post.
I'm not a Ruby programmer.

References
 System V Application Binary Interface: AMD64 Architecture Processor Supplement  [?]

The Broken Promises of MRI/REE/YARV : ruby http://www.reddit.com/r/ruby/comments/ihaz1/the_broken_promises_of_mrireeyarv/

■_

2011年07月07日

■_

あとで書く

7/9 書くこと忘れたw

■_ 旋回

関数型プログラミング言語Haskell Part14 

1000 デフォルトの名無しさん [sage] 2011/07/07(木) 08:35:43.25 ID: Be:
    1000だとHaskell で作られたOSが世界を旋回する。 

「席巻する」かなあ?

■_ Perl 6

Perl 6ネタその1.

June 26 2011: Signatures :: Strangely Consistent

June 26 2011: Signatures

We haven't implemented a Fibonacci subroutine yet. Let's do that.

sub fib($n) {
    return 0 if $n == 0;
    return 1 if $n == 1;

    return fib($n - 1) + fib($n - 2);
}

(略)

What's worse, we can't just solve this by slapping a NonNegativeInt type on $n either, 
because there is no such type in Perl 6. Instead, we can do one of two things.

The first thing we can do is to use a where clause:

わたしたちが最初にできることは where clause です


sub fib(Int $n where { $n >= 0 }) {
    ...
}

Now people will get this when they try to call fib(-1):

Constraint type check failed for parameter '$n'

I guess you can see how where clauses complement named types quite nicely. We can check
anything we want inside of those. And it's shorter than writing something like this:

この内側ではわたしたちは望むものすべての検査ができ、それは次のように書くよりも短いものです:

sub fib(Int $n) {
    die "fib can't handle negative numbers!"
        unless $n >= 0;

    ...
}

The second thing we can do is define a NonNegativeInt:
できることの二つ目は NonNegativeInt の定義です:

subset NonNegativeInt of Int where { $_ >= 0 };

sub fib(NonNegativeInt $n) {
    ...
}

So... subset gives us the ability to create new, narrower types. We'll see lots more 
about type creation in the next few days.

subset, as it happens, also uses a where clause. Of course that's because we're still 
doing essentially the same check, only we're declaring it outside of the signature. 
Note how we can't use $n inside the where clause, because $n only exists within the 
context of fib. But the topic variable $_ within where clauses means "the value 
we're talking about", and that's what we need.

subset もまた where clause を使っています。
もちろん、それは本質的に同じ検査をわたしたちが行っているからであり、
シグネチャーの外側で宣言しているからです。
where clause の内側で $n を使えないことに注意してください。
それは、$n は fib のコンテキストの内側でだけ存在しているものだからです。
But the topic variable $_ within where clauses means "the value we're talking about",
and that's what we need.


When should you use where clauses directly in the signature, and when should you 
define subtypes? There's no right or wrong here, but it makes a lot of sense to 
declare a subtype if you plan to use that particular constraint in a lot of different 
situations.

いつ、シグネチャーの中で直接 where clauses を使うべきなのか、いつ subtypes を
定義すべきなのか? 正解も間違いもありません。けれども
多くの異なるシチュエーションにおいて特定の制約を使いたいと考えているのであれば
subtype を宣言することに意味があるでしょう。

Let's end today's post with a nice feature that we're now prepared to fully appreciate: 
multi subs. They're simply subroutines with the same name but different signatures:

multi sub fib(Int $n where { $n == 0 }) { 0 }
multi sub fib(Int $n where { $n == 1 }) { 1 }

multi sub fib(Int $n where { $n  > 1 }) { fib($n - 1) + fib($n - 2) }

Clearly, it gets rid of a bit of conditionals, by pushing things into signatures 
instead. In fact, we can write the first two multis even shorter:

明らかに、シグネチャーに押し込めることによっていくつかの条件を取り除いています。
実際には、最初の二つの multi はもっと短く書けます:

multi sub fib(0) { 0 }
multi sub fib(1) { 1 }

multi sub fib(Int $n where { $n > 1 }) { fib($n - 1) + fib($n - 2) }

Look how close that is to the definition at the top of the Wikipedia page.

Multis are a great way to divide related but different behaviors into different subs. 
More about clever ways of subdividing things tomorrow, when we talk about classes.

multi は、関係はしていても異なる振る舞いのものを別々の subs へと分割するための
great way です。


うまいといえばうまいやり方なんだろうけど、 multi sub fib(Int $n where { $n == 0 }) { 0 } のように、where なんとかまで書けるのはやり過ぎな気がしないでも…

■_ Perl 6

毎度おなじみPerl 6 ネタ。その2

June 28 2011: Roles :: Strangely Consistent

Strangely Consistent
Musings about programming, Perl 6, and programming Perl 6

Having learned how to create classes, we might go on to create them to our hearts' content:

class Hammer {
    method hammer($stuff) {
        say "You hammer on $stuff. BAM BAM BAM!";
    }
}

class Gavel {
    method hammer($stuff) {
        say "You hammer on $stuff. BAM BAM BAM!";
    }
}

class Mallet {
    method hammer($stuff) {
        say "You hammer on $stuff. BAM BAM BAM!";
    }
}

But... notice something here? These three classes contain the exact same method, 
repeated in each class. We have to do that if we want each of Hammer, Gavel and Mallet 
to have the ability to hammer. (And that's reasonable.) But it's a pity that we have 
to triplicate the method.

でも、ここでなにかに気がつきませんか?
これら三つのクラスはまったく同じメソッドを持っていて、それぞれのクラスで繰り返し
書かれています。わたしたちは Hammer、Gavel、Mallet のそれぞれに hammer の能力を
持たせたければそうしなければなりません(また、それが reasonable です)。
けれども triplicate the method しなければならないことは pity です。


Why is it a pity? Well, it's more to write, for one thing. Also, the methods might not 
be this close to each other in a real-world example, and one day we may decide to 
change something in the hammer method, not realizing that it's in three different 
places... which generally leads to a bunch of pain and suffering.

なぜそれが pity なのでしょうか? それは、ひとつのことに対して多くのことを書かねば
ならないからです。また、このメソッドは real-world example のそれぞれに対して
密着したものではないかもしれませんし、ある日、hammer メソッドのどこかを変える
決断をするかもしれません。それも、そのメソッドが実は別々の場所三箇所にあることに
気がつかずに…そしてそれは、一般的に言って
bunch of pain and suffering につながるものです。

So here we are, with this new toy, classes, and already they exhibit a problem. We'd 
somehow like to re-use the hammer method in each three classes.

A new concept, the role comes to our rescue:

新しいコンセプト role がわたしたちを窮地から救うためにやってきました。

role Hammering {
    method hammer($stuff) {
        say "You hammer on $stuff. BAM BAM BAM!";
    }
}

(略)

今流行の? Trait のようなものとか聞いたことが> Role

■_

■_

2011年07月06日

■_

Shibuya Perl Mongers : Shibuya Perl Mongersテクニカルトーク#16 で発表してきました。

■_

あとで書く

2011年07月05日

■_

二日目。

すでにもういろいろと以下略

■_ .gmo

というわけで、gettext で使用する .mo ファイルのフォーマットなんぞを調べていたり。 まずはマニュアル。

GNU `gettext' utilities

10.3 The Format of GNU MO Files

The format of the generated MO files is best described by a picture, which appears below.

The first two words serve the identification of the file. The magic number will always 
signal GNU MO files. The number is stored in the byte order of the generating machine, 
so the magic number really is two numbers: 0x950412de and 0xde120495.

(略)

The size S of the hash table can be zero. In this case, the hash table itself is not 
contained in the MO file. Some people might prefer this because a precomputed hashing 
table takes disk space, and does not win that much speed. The hash table contains 
indices to the sorted array of strings in the MO file. Conflict resolution is done by 
double hashing. The precise hashing algorithm used is fairly dependent on GNU gettext 
code, and is not documented here.

このハッシュテーブルはMOファイルにあるソート済み文字列配列へのインデックスを保持します。
衝突の回避は二重ハッシングによって解決されます。
ここで使われている精確なハッシュアルゴリズムは GNU gettext のコードに依存していて、
このドキュメントには記載されていません。

(略)
             byte
                  +------------------------------------------+
               0  | magic number = 0x950412de                |
                  |                                          |
               4  | file format revision = 0                 |
                  |                                          |
               8  | number of strings                        |  == N
                  |                                          |
              12  | offset of table with original strings    |  == O
                  |                                          |
              16  | offset of table with translation strings |  == T
                  |                                          |
              20  | size of hashing table                    |  == S
                  |                                          |
              24  | offset of hashing table                  |  == H
                  |                                          |
                  .                                          .
                  .    (possibly more entries later)         .
                  .                                          .
                  |                                          |
               O  | length & offset 0th string  ----------------.
           O + 8  | length & offset 1st string  ------------------.
                   ...                                    ...   | |
     O + ((N-1)*8)| length & offset (N-1)th string           |  | |
                  |                                          |  | |
               T  | length & offset 0th translation  ---------------.
           T + 8  | length & offset 1st translation  -----------------.
                   ...                                    ...   | | | |
     T + ((N-1)*8)| length & offset (N-1)th translation      |  | | | |
                  |                                          |  | | | |
               H  | start hash table                         |  | | | |
                   ...                                    ...   | | | |
       H + S * 4  | end hash table                           |  | | | |
                  |                                          |  | | | |
                  | NUL terminated 0th string  <----------------' | | |
                  |                                          |    | | |
                  | NUL terminated 1st string  <------------------' | |
                  |                                          |      | |
                   ...                                    ...       | |
                  |                                          |      | |
                  | NUL terminated 0th translation  <---------------' |
                  |                                          |        |
                  | NUL terminated 1st translation  <-----------------'
                  |                                          |
                   ...                                    ...
                  |                                          |
                  +------------------------------------------+

この図でだいぶ助かったのですが、ハッシュテーブルの役割が今ひとつわからなかった。 .mo ファイル生成時に作らないように指定することもできるし、 ハッシュテーブルのエントリに書かれる内容が1から始まる数字(最大値は文字列テーブルの 大きさで、0は空のエントリを示す)だったりでなんのためにあるのかと。 文字列テーブル自体は二分検索できるようにソートされるので、 検索目的というのも…と思いつつ、gettext のソースコードをいくつか読んでみると 一応このハッシュ経由の検索もやる場合があるらしいです。


gettext-tools/src/write-mo.c write_table
gettext-runtime/src/intl/loadmsgcat.c _nl_load_domain
gettext-runtime/src/intl/dcigettext.c _nl_find_msg

このへん。

gettext や .gmo (.mo) ファイルの話はこのあともまた書きます。

■_

■_ 戦う司書

TOKYO MX アニメ総合スレ 21

311 メロン名無しさん [sage] 2011/07/03(日) 23:02:45.84 ID:???0 Be:
    ベン・トー TVアニメ今秋放送決定

    戦う司書 TOKYO MXで放送(8月8日より毎週月曜-木曜 27:30-29:00)

    ソースはジャンプSQ8月号のSDMP 

312 メロン名無しさん [sage] 2011/07/03(日) 23:34:56.14 ID:???0 Be:
    戦う司書は絶対誰得だのなんだの言うヤツが出るだろうが
    俺得なのでOK 

313 メロン名無しさん [sage] 2011/07/03(日) 23:58:18.97 ID:???0 Be:
    好きだったけどBS11で見たからいいや 

314 メロン名無しさん [sage] 2011/07/04(月) 00:08:12.57 ID:???0 Be:
    見た事無いや
    地上波では初? 

315 メロン名無しさん [sage] 2011/07/04(月) 00:13:37.99 ID:???0 Be:
    そう
    本放送はアニマックスとBS11だけだったからな 

316 メロン名無しさん [sage] 2011/07/04(月) 00:20:49.35 ID:???O Be:
    戦う司書楽しみだわ

324 メロン名無しさん [sage] 2011/07/05(火) 01:19:54.33 ID:???0 Be:
    公式更新されてた
    http://www.bantorra.com/news.html

    全27話なので1日3話ずつ放送して9日間で全話放送 

325 メロン名無しさん [sage] 2011/07/05(火) 06:51:19.80 ID:???0 Be:
    戦う司書やっとやるんだ
    面白いからみんな見てくれると良いけど

うれしいはうれしいけど 戦う司書 TOKYO MXで放送(8月8日より毎週月曜-木曜 27:30-29:00) 集中してやるんですね。録画して観ている時間がとれるかなあ。

2011年07月04日

■_

初日。

■_ strncpy

どの本だったか、あるいは雑誌の連載記事だったかは思い出せませんが、 割と名の知れた方が strncpy をまさしく strncpy is a safer alternative to strcpy として紹介していたような…

strncpy? just say no

All content outside of comments is copyrighted by Lars Wirzenius, and licensed under a 
Creative Commons Attribution-Share Alike 3.0 Unported License. Comments are 
copyrighted by their authors.

This is a rant. I've made it in various forms in various places over the years, and I 
think it's time to put it somewhere so I can point people at it, and stop repeating 
myself.

Here's the pebble in my shoe: people keep claiming that strncpy is a safer alternative 
to strcpy. It's not. It's a slower function that is not going to make you significantly
safer.

#pebble 小石
strncpy は strcpy の safer alternative であると皆が主張し続けています。そうではないのに。
strncpy はあなたをはっきりと安全に導いていくれるものではない、遅い関数です。

The problem with strcpy is that it's somewhat easy to overflow the target array:
strcpy にまつわる問題はそれが target array でオーバーフローし易いといったものです:

    char src[] = "hello, world";
    char dst[5];
    strcpy(dst, src); // Oops.

The suggested alternative with strncpy would be this:
strncpy を使った代替案はこんな感じになるでしょう:

    strncpy(dst, src, sizeof(dst));

strncpy gets the size of the destination array as a parameter, and can therefore make sure
the string will fit there. Problem solved? Not so much.

strncpy はパラメーターとして、destination array のサイズを取ります。そして
これによって文字列が destination array に fit することを確実にできるのです。
問題は解決されたでしょうか? いいえ、そうでもないのです。

Every time you do any string handling with C's native string types and functions, you need
to make sure you have allocated enough memory for each string, you need to keep track of
how much memory you've allocated, and you neet to make sure the zero byte ('NUL', '\0') is
put there correctly. This is a lot of details to keep track of, and it's not surprising
things sometimes go wrong.

C のnative string の型や関数でなんらかの文字列処理を行う度に、
各文字列に対して充分なメモリーを割り当てていることを保障する必要があります。また、
どの程度の大きさのメモリーを割り当てたのかを記録しておく必要もありますし、
ゼロのバイトが正しく置かれたことも保証しなければなりません。
This is a lot of details to keep track of, and it's not surprising things sometimes go wrong.


If your arrays are allocated statically, which is the simplest, but least useful case, you
need to something like this with strcpy:

最も単純ではあってもほとんど有用でないケースとして、もしあなたの使う配列が静的に割り当てられた
ものの場合、次のように strcpy を使う必要があるでしょう:


    if (strlen(src) + 1 > sizeof(dst))
        panic(); // or however you want to handle your errors
    strcpy(dst, src);

The +1 after strlen is to make room for the zero byte (NUL, '\0') that is used in C to 
indicate the end of a string.

この strlen のあとにある +1 は、Cにおいて文字列の終端を示すのに使われるゼロを納めるバイト
(NUL、'\0')のための領域です。


With strncpy, your code is slightly simpler. This is its attraction.

strncpy を使うと、コードが格段に単純になります。これが strncpy の attraction です。

Problem is, this only works if dst is an array defined within the scope of the code. 
If, as is common, you have received dst as an argument to a function, sizeof(dst) is 
the size of a pointer to an element of the array, not the size of the array. So now 
you need to track the size explicitly in a second variable:

問題は、これがdstがそのコードが置かれているスコープで定義された配列であったときにのみ
うまく動作するということです。仮に、よくあるようにdst を関数に対する引数として
受け取った場合、sizeof(dst) は配列の大きさではなくその配列の要素へのポインターの大きさと
なってしまいます。ですから、ここで二つめの変数を用意して自前で配列の大きさを
記録しておかなければなりません:

    strncpy(dst, src, dst_size);

Further, strncpy has an unfortunate error handling mode: it merely fills the destination
array and stops. It does not indicate failure in any way. It does not terminate the target
array with a zero byte. Since all C string processing assume the zero byte is there, as soon
as you try to use dst as a string, you're in trouble.

さらに、strncpy には unfortunate error handling mode があります:
この関数は単に destination array を埋めて止まるだけなのです。
何らかの手段でもってエラーを示すことはありません。
target array をゼロのバイトで終端することもありません。
すべてのC文字列の処理ではゼロのバイトがあることを仮定していますから、
このdstを文字列として使おうとした途端、トラブルが降りかかることになります。

But luckily you can check for that before you call strncpy:

しかし幸運にもstrncpyを呼び出す前にチェックができます:


    if (strlen(src) + 1 > dst_size)
        panic(); // or whatever
    strncpy(dst, src, dst_size);

By this time, the code is equally hard whether you use strcpy or strncpy. With strncpy 
you often waste some extra time, though, filling the unused parts of the target array 
with zero bytes: they're almost never necessary.

この場合、コードはstrcpyとstrncpとでほとんど同じものとなります。
ただし、strncpyを使った場合には多少余計な時間を浪費することになるのがほとんどです。
それは、target array の未使用部分をゼロのバイトで埋めていく手順が入るからですが
これはほとんど不必要なものです。

Alternatively, you can force the zero byte there yourself, silently truncating a string.

代替策として、自分自身でゼロのバイトを埋め込むことを強制して
こっそりと文字列を丸めることが可能です。


    strncpy(dst, src, dst_size);
    dst[dst_size - 1] = '\0'; // let's hope dst_size > 0

If your string handling is OK with strings being randomly shorter than they should be, 
possibly you could replace all of them with empty strings, and save yourself a world of
pain.

もしあなたの文字列処理が本来あるべき長さよりもランダムに短くなる文字列に対しても問題ない
のであれば、すべての文字列を空文字列に変えることができて
save yourself a world of pain.

Instead of strncpy, use snprintf instead. It has sensible error behavior, and is much 
more versatile:

strncpy の代わりに、snprintfを使いましょう。
この関数は sensible error behavior を備えていて、また、ずっと汎用的なものです:

    n = snprintf(dst, dst_size, "%s", src);
    if (n > dst_size)
        panic();

snprintf still isn't very nice to use. It still requires you to allocate memory 
yourself, and keep track of the size of each array manually.

それでも snprintf は very nice to use ではありません。
まだメモリーの割り当てを自分でやらなければなりませんし、
各配列の大きさも手作業で記録しておかなければなりません。

The real solution is to abandon C's antiquated string handling, and use a more sensible
helper library instead. There's a bunch of them around, though none have gained much
popularity. I'm not going to name any of them, but just imagine how much nicer it would
be to write code like this instead:

real solution は C の antiquated string handling を諦めて、より sensible な
ヘルパーライブラリを使うようにすることです。そういったものはたくさんありますが、
much popularity を得たものはありません。



    Dynstr *src = dynstr_new_from_cstring("hello, world\n");
    Dynstr *cat = dynstr_cat_many(src, src, src, src, src, NULL);
    Dynstr *dog = dynstr_substr(cat, 15, 5);

Let the library take care of memory allocations and related tracking, and concentrate on
real problem solving instead.

We did this in Kannel, back in 1999, and it wiped out all the buffer overflow problems 
(until a co-worker decided it was "more efficient" to use native C strings 
instead, promptly introducing a buffer overflow).

All of this string handling is, of course, way nicer in higher level languages. In fact,
whenever you need to deal with string handling in C, it is probably a sign that you should
consider switching to a higher level language instead.

But whatever you do, stop claiming that strncpy is safe or solves any real problems strcpy
has.

Update: Fixed "It does terminate" to say "It does not terminate". 
Thanks to Matthew Garrett for pointing that out.

Update2: Fixed example call to snprintf.

strlcpy

You could also mention the OpenBSD-originated strlcpy, even though it is only marginally
better than strncpy.

strncpy より優れたもののように見えるだけかもしれませんが、
OpenBSD起源の strlcpy にも言及した方が良いかもしれません。

Comment by Paul

snprintf ftw

snprintf はどうでしょう

strlcpy(dst,src,dst_size) → snprintf(dst_size, dst, "%s", src);

Should be the same semantics, and it's completely standard in C99.

これは同じ semantics になっているはずですし、snprintf の方は C99 において
完全に標準のものです。

Comment by Lars Wirzenius


@lars, re: syntax

You entered the syntax for snprintf correctly in the article but not in your followup comment.
Should be snprintf(dst, dst_size, "%s", src) according to the man page.

Thanks for the article, btw! :)

Comment by Carl


strbuf

Git has a very nice "strbuf" module which provides a simple abstraction around C
strings. Unfortunately, nobody has extracted it from Git for use as a general-purpose
library.

Comment by JoshTriplett


re: strbuf

A fragment of git's strbuf module has escaped into the wild. But presumably a general-purpose
version would need a different name to avoid conflicting with the other strbufs out there.

I like the snprintf hint.

Comment by JonathanNieder 

■_

AwkのGNU実装、「Gawk 4.0」が登場 - SourceForge.JP Magazine : オープンソースの話題満載


 Gawk 4.0は、バージョン3.1.8以来のメジャーリリース版となる。多数の変更が加えられてお
り、旧バージョンとの互換性が損なわれる変更もあるという。たとえばsubおよびgsubコマンド
の挙動はデフォルトでPOSIX 2008準拠となり、また正規表現における文字クラス指定子の挙動は
すべてのロケールで統一されるようになった。これにより、たとえば「[a-z]」という正規表現
が特定ロケールでは大文字アルファベットにマッチする、という挙動がなくなるという。そのほ
か、POSIXモードでは文字列の比較にロケールに応じた文字列比較を行う「strcoll」および
「wcscoll」を利用するように変更されている。

この「[a-z]」という正規表現が特定ロケールでは大文字アルファベットにマッチする という書き方は不十分というか、書き手がよくわかってなかったんじゃないかという感じが。 こう書かれると、すべての大文字にもマッチする(大小文字の区別を無視する)ようにも取れますよね。 でも実際には、「ほぼすべて」だったりします(ってのが混乱を招いた一因とも思いますが)。

ありがちなのは、 aAbBcCdDeE…xXyYzZ のように小文字大文字が交代ででてくるパターン。 これだと、[a-z] には Z が入りません。

■_

2011年07月03日

■_

またやってしまった

感想知りたい人いるかしらん。

■_ ネタバレ

「星を継ぐもの」漫画版のお話。

星野之宣を語れ Part9

484 名無しんぼ@お腹いっぱい [age] 2011/07/03(日) 08:56:15.03 ID:y1yxXhpm0 Be:
    原作未読者のためのネタバレ

    J5がガニメデに到着したとたん宇宙船遺跡が突如崩れ、チャーリーが地球人である確たる証拠が出現!
    ダンチェッカーが「五万年前、人類は月で製鉄をしていた」説をぶちあげ完結。

    おや、何だ皆さんその目つきは。こっち見んな! 

485 名無しんぼ@お腹いっぱい [sage] 2011/07/03(日) 09:06:54.48 ID:Gq0SI5nj0 Be:
    それ教授違いwww 

486 名無しんぼ@お腹いっぱい [sage] 2011/07/03(日) 09:29:30.19 ID:MLz7skAx0 Be:
    踏鞴を踏んじまったw 

487 名無しんぼ@お腹いっぱい [] 2011/07/03(日) 09:33:55.85 ID:5dhCJpNu0 Be:
    原作未読者のためのネタバレ Ⅱ

    ガニメデに到着したJ5は宇宙船遺跡を改造し,エクスカリバーを建造。
    謎の敵を倒すため,銀河の彼方へ飛び立っていった。
    一方,チャーリーが地球人である確たる証拠が出現。
    ダンチェッカーは「五万年前、人類は月で製鉄をしていた。
    やがて地球に降り立ったチャーリーらは古代ヒッタイト帝国を
    うちたてた。帝国崩壊後,チャーリーの末裔は日本に渡り
    たたらを踏み,赤鬼伝説となった」説をぶちあげ完結。

    おや、何だ?皆さんその目つきは?。こっち見んな! 

488 名無しんぼ@お腹いっぱい [sage] 2011/07/03(日) 10:42:26.24 ID:Gq0SI5nj0 Be:
    ちょwww それだと尻切れトンボで終わっちゃうwww 

489 名無しんぼ@お腹いっぱい [sage] 2011/07/03(日) 11:47:59.77 ID:cyDgOiQH0 Be:
    ガニメデの地下に鉄製の神社が 

491 名無しんぼ@お腹いっぱい [sage] 2011/07/03(日) 14:02:45.98 ID:L/7Z6bOO0 Be:
    >>487
    ガニメデに到着したリン達は、沈んだ宇宙船を復活させ、
    ミネルヴァ再興のための祭りをはじめた。
    時を同じくして、地球から、ラッセララッセラと踊り狂いながら、
    ルナリアンの子孫達がガニメデを目指す。

    スヴェレンセン達は、過去のスーパーコンピュータの模造品を
    製作し、それらを向かいうつ。

    活発な火山活動を開始したミネルヴァを救うことが出来るのか?

    おや、何だ?忌部さんその目つきは?こっち見んな! 

過去の星野作品を知ってないと通じないネタバレw

■_

Zed がなにかやるとたいていredditが盛り上がるという。

"Learn C the hard way": Zed Shaw's started work on a book about C programming : programming

"Learn C the hard way": Zed Shaw's started work on a book about C programming (learncodethehardway.org)


This man hates to do nothing. He's always writing something.


Zed's the first true man/machine hybrid. I'm sure of it.


First? What about Richard Stallman?


Stallman is at least 10% beard.


Also, self-righteous anger. Unless that's the beard.


I don't have any problem with Zed Shaw, like a lot of folks do...he seems a pretty 
decent guy who tries to do good things. And he's written a lot of free software, which 
many people find useful. He's a net positive for the world, I reckon.

But, there have been hundreds of attempts to better K&R, and all have failed. 
K&R is an awesome book. There is no filler, no bullshit, no misunderstandings of 
the language, and every word counts. I'd tried to learn C from a dozen or more books, 
and it never "took" until K&R.

I cannot imagine a world in which Zed Shaw can write a better book about C than 
K&R.

In other words, there's no need to screw around waiting for Zed to finish his book. Go 
pickup a copy of K&R, read it, work with the examples, and you'll learn C.


When I learned C, the only book was K&R. It is a remarkably clear and concise 
specification of the language. Not necessarily the best learning text. It assumes that 
the reader is already familiar with structured languages and machine architecture.


One could argue that C is not the best learning language.

I will concede that I was already a programmer with experience in a number of 
languages before reading K&R. I'd even read a bunch of C books. But, because they 
were so often wrong, so often misguided, so often hastily slapped together by people 
who didn't actually understand the language (even if the examples worked, the 
descriptive text often misled about why).

I just have such a very high level of appreciation for K&R and such a very poor 
view of other C books I've read, that I'm leery of the entire category of "C 
books not written by K&R".


I had read many programming language tutorial texts by the time I was assigned K&R 
in a second-year computer science class. Within a few pages I was over the moon with 
happiness. Finally, a book which assumed you already knew how to program in a 
structured language, a book which spoke to the reader at just the right level.

I no longer have a copy of that book (1st edition K&R) but I remember sentences 
like "C has the traditional if statement. [Example] The else clause matches the 
nearest if. [Example]." They realized that by the time a programmer in the 1980s 
was learning C, he or she had already learned Pascal or Algol or Ratfor or Structured 
Basic, etc. Hooray! A book that doesn't treat me like an idiot!

And that's why K&R is so goddamned wonderful. (And why it's a bad choice for 
anyone's first programming textbook.)

Stallman is at least 10% beard.てw

完成はまだみたいだけど、是非誰か訳して(ry

■_

で、そのうわさの Zed の C 本。

Learn C The Hard Way A Clear & Direct Guide To Modern C Programming

Learn C The Hard Way

A Clear & Direct Guide To Modern C Programming

Zed A. Shaw

Preface

You can grab the PDF Preview to take a look. Otherwise this is a rough dump of the 
book as I build the structure.

There is a mailing list for the book at lcthw at librelist.com which you can join. I'll 
be doing announcements as new material is up, and you can ask questions if you get 
stuck or have comments.

Finally, don't forget that I have Learn Python The Hard Way, 2nd Edition which you 
should read if you can't code yet. LCTHW will not be for beginners, but for people 
who have at least read LPTHW or know one other programming language.

最後に、すでにわたしは Learn Python The Hard Way, 2nd edition を完成させていることを
忘れないでください。あなたがもしまだコーディングできないのであれば、こちらを読むべき
です。LCHTHW は初心者向けのものにはならないでしょう。この本は少なくとも LPTHW を
読みきった人か、何か別のプログラミング言語を知っている人に向けたものです。

Chapter 1

Introduction: The Cartesian Dream Of C
# Cartesian Dream ってなんじゃろ。ぐぐってもよくわからん

       Whatever I have up till now accepted as most true and assured I have gotten either
       from the senses or through the senses. But from time to time I have found that the
       senses deceive, and it is prudent never to trust completely those who have deceived
       us even once.

                                 (Rene Descartes, Meditations On First Philosophy)

If there ever were a quote that described programming with C, it would be this. To 
many programmers, this makes C scary and evil. It is the Devil, Satan, the trickster 
Loki come to destroy your productivity with his seductive talk of pointers and direct 
access to the machine. Then, once this computational Lucifer has you hooked, he 
destroys your world with the evil ”segfault” and laughs as he reveals the trickery 
in your bargain with him.

If there ever were a quote that described programming with C, it would be this.
多くのプログラマーにとって、この本は C を scary で evil なものにします。


But, C is not to blame for this state of affairs. No my friends, your computer and the 
Operating System controlling it are the real tricksters. They conspire to hide their 
true inner workings from you so that you can never really know what is going on. The C 
programming language's only failing is giving you access to what is really there, and 
telling you the cold hard raw truth. C gives you the red pill. C pulls the curtain 
back to show you the wizard. C is truth.

Why use C then if it's so dangerous? Because C gives you power over the false reality 
of abstraction and liberates you from stupidity.

それほどに危険であるのなら、なぜ C を使うのでしょうか?
それは、C があなたに
over the false reality of abstraction
な力を与えてくれ、また、あなたを stupidity から解放してくれるからです。

(略)

ぐはーっなんか訳せねえ~っ○| ̄|_

7/5追記: いろいろアドバイスをいただきました。 Rene Descartes ← この人のことを良く知らんといかんわけですね ○| ̄|_

■_ サイン会

日本Ruby会議2011本編受付方法について, サイン会のお知らせ - RubyKaigi Nikki(2011-07-03)

* サイン会のお知らせ

日本Ruby会議2011実行委員のしまだです。

日本Ruby会議2011では、会場にいる Rubyist な著者の皆さんによるサイン会を実施いたします。 ラインナップおよびスケジュールは以下を予定しています(追加・変更となる場合がありますので、ご注意ください)。 ジュンク堂書店 RubyKaigi 店にて対象の書籍をお買い求めの上、皆様どうぞご参加ください。

日	時	名前:対象書籍
7/16(土)	12:00-13:30	まつもとゆきひろ:『7つの言語 7つの世界』(オーム社)
7/17(日)	12:00-13:30	高橋征義, 松田明, 諸橋恭介 :『Rails3レシピブック 190の技』(ソフトバンク クリエイティブ)
	15:40-16:10	角征典,濱崎健吾:『ウェブオペレーション』(オライリー・ジャパン)
7/18(月)	12:00-13:30	西村直人, 角谷信太郎:『アジャイルサムライ』(オーム社)

これは「7つの言語~」は他でフラゲできないなあw ってこの会場が最速だったりして。

■_

2011年07月02日

■_

あ、メールの返事書かないと。

星を継ぐもの 1 (ビッグコミックススペシャル)
油断してたら買い損ねるところだった(ってまあ増刷されますけど)。

■_ メタ

C++ が LL かというのはおいといて、確かに面白そう

Gauche > Archives > 2011/07/02

2011/06/30 23:34:27 PDT shiro

  RT: @knsmr: 今年のLLイベントはパネルのモデレータとして登壇予定です。あ、司会が調整中だ。
     言って良かったのかな。Gaucheのshiroさん来てくれないかなぁ
     / Lightweight Language Planets : メタプログラミングの光と闇 http://t.co/iFaHZo1

これはおもしろそうなセッションだ。けど直前までバンクーバーにいるのでキツいっす。

2011/07/01 21:26:51 PDT とおる。

C++ からはだれか参戦しないのかな。

2011/07/01 21:28:02 PDT shiro

C++の「メタプログラミング」は別の言語みたいなもんだからなあ (でも見てみたい、超絶テンプレートメタプログラミング)

2011/07/01 21:30:56 PDT とおる。

なんか、人が書いてるのを見ると自分にも出来そうと思うんですけど、いざ自分でやろうとするとなぜか出来ないんですよねぇ。魔術的です。

我こそはというC++使いの人、是非。 って窓口どこー?

■_ red-black tree

難しいってのはどの辺りを指していってるのだろうか? 平衡木全体に共通する(rotateとか)部分か、赤黒木に特有の部分か。 なんとなーく、rotate そのものか、赤黒の色分けのところかなあと思ったり。

3時間ほどかけて赤黒木について勉強したのですが、、、 - Yahoo!知恵袋


3時間ほどかけて赤黒木について勉強したのですが、、、

解説サイトを読んだり書籍を読んだりしたのですが難しくてなぜうまく動くのかあまり理解できませんでした。
世の平均的なプログラマなら大体分かるものなのでしょうか?
わからない私が低レベルなのでしょうか?

頭の悪い私のためにどなたかずばっとわかる本質、重要な要点の解説をお願いします。

つーか「本質、重要な要点の解説」というので何を期待しているのかと。

自分も AVL木 で rotate の処理をしたときの木の変化がなかなか理解できなくて頭かきむしったなあw あれ、(Lisp の) リストで表現してみるとわかりやすいんじゃないかなあと思ったり。

■_ Smalltalk: the Software Industry's Greatest Failure

また釣り狙いのタイトルで中身は…と思ったのだけどどうなんだろ。

って、redditで今日見かけたものだけど、記事の日付は2月だねえ

Richard Kulisz: Smalltalk: the Software Industry's Greatest Failure
 
Sunday, February 27, 2011
Smalltalk: the Software Industry's Greatest Failure

Every time I think about the miserable state of the software industry, it always comes 
back to one thing: the Smalltalk programming language.

The failure of the software industry is the failure of its greatest tools, the 
programming languages and operating systems. The failure of programming languages is 
the failure of the only natural and useful programming languages, the OO languages. 
And the failure of OO languages is the failure of the only OO language worth speaking 
of, Smalltalk.

industry なソフトウェアの失敗とは、その greatest tool であるプログラミング言語と
オペレーティングシステムの失敗です。プログラミング言語の失敗とは、natural で
useful なプログラミング言語、つまりオブジェクト指向言語の失敗です。そして
オブジェクト指向言語の失敗とは、語るに値する唯一のオブジェクト指向言語、すなわち
Smalltalk の失敗です。

Programming languages started with the imperative paradigm but they rapidly bifurcated 
into two mutually contradictory paradigms - functional and OO. Once the bifurcation 
was complete, the imperative paradigm ceased to have any importance. Beyond being a 
tool of mentally incompetent brainwashed morons and those desperately maintaining 
obsolete code of course.

プログラミング言語は命令型パラダイムから始まりましたが、即座に二つの mutally
contradictory なパラダイムに分化しました。関数パラダイムと
オブジェクト指向パラダイムがそれです。この分化が完了したのち、
命令型パラダイムはなんらの重要性を持たなくなりました。
Beyond being a tool of mentally incompetent brainwashed morons and those desperately maintaining obsolete code of course.
#えーと訳しづらいなこれ。
#命令型のパラダイムと一緒に、imcompetent brainwashed moron なツールや
#絶望的なまでにメンテナンス困難なコードもまた重要でなくなった。という感じ?

The functional paradigm rejects all notion of modifiable state and orders everything 
around verbs so that all sentences are verb-object-object. The functional paradigm 
rejects state and objects so violently that it denies subjects exist. As a direct 
consequence it is blatantly unnatural to the human brain, contrary to physical reality, 
and contrary to human consciousness. Only math lovers find the functional paradigm 
attractive or useful which makes it useless to the rest of humanity.

The object-oriented paradigm is dominated by Smalltalk. Java for example doesn't even 
remotely qualify as object-oriented having been conceived as a deliberately inferior 
and broken pseudo-OO version of Smalltalk. The problem is Smalltalk is a failure as an 
OO language and has definitely not passed the test of time. And I'm not talking about 
popularity either. I couldn't care less about popularity of programming languages 
among brainwashed mental incompetents.

The failure of Smalltalk is two-fold. First, the fact that its rules are at least 
twice as large as they need to be. Because for every general rule of Smalltalk that 
someone has to assimilate in order to master the language, there is a specific rule 
(an exception to the general rule) that must ALSO be memorized. There are 8 such 
exceptions and they are:

(略)

全文訳すのはきつい、つか無理ぽ? ○| ̄|_

■_ Perl 6

なんか知らない(知らなかった)ことがあとからあとから。

June 24 2011: Types :: Strangely Consistent

Strangely Consistent
Musings about programming, Perl 6, and programming Perl 6

(略)

Yes, subroutine parameters can be given types as well:
サブルーチンのパラメーターには型を与えることもできます:

sub duplicate(Str $s) {
    return $s ~ $s;
}

Now people have to call your duplicate subroutine with a Str value.
これで、duplicate サブルーチンを呼び出す人は Str の値でもって呼び出さなければ
ならなくなりました。

say duplicate("hi!");      # "hi!hi!"
duplicate(42);             # Expected Str, got Int

Actually, we might decide that a type error there is a bit harsh. After all, Perl 
figures out that 42 ~ 42 is a string concatenation of two things that happen to be 
Ints, so why shouldn't duplicate? We'd like to loosen the restriction a little, be a 
bit more forgiving. That's when we use the Cool type:

sub duplicate(Cool $s) {
    return $s ~ $s;
}

say duplicate("hi!");       # "hi!hi!"
say duplicate(42);          # "4242"

Cool is a type that brings together all those values in Perl that traditionally are 
exchangable for one another: Str, Int, Num, Bool, Array, Hash. Not all scalar values 
are Cool; Regex isn't Cool, for example.

Cool は Perl おいて伝統的に交換可能 (exchangable for one another) であったすべての
値である Str、Int、Num、Bool、Array、Hash をまとめる型です。
すべてのScala値がCoolであるというわけではなく、たとえば Regex は Cool ではありません。

We're starting to see that some types "contain" other types, in the sense 
that a Str value is always a Cool value, but a Cool value doesn't have to be a Str 
value. The tree of all such containments is called the type hierarchy, and the bits 
we've talked about so far hang like this in that hierarchy:

                             Mu
                              |
                              |
                     +--------+---------+
                     |                  |
                     |                  |
                    Any              Junction
                     |
                     | 
             +-------+---------+-------+
             |                 |       |
             |                 |       |
           Cool             Whatever Routine
             |                         |
             |                         |
 +----+---+---+----+-----+        +----+----+
 |    |   |   |    |     |        |         |
 |    |   |   |    |     |        |         |
Bool Int Num Str Array Hash      Sub      Regex

Many important types are collected under Cool. Cool contains a great many useful 
methods, that are thereby all accessible from the subtypes of Cool.

重要な型の多くが Cool の下に集められています。Cool は有用なメソッドをとても
たくさん抱えていて、それは Cool のサブタイプからも全部アクセス可能なものです。

(略)

型チェックきちんとやると厳しすぎる一面があるからCoolという型?を導入して…?

Any と Junction の上にある Mu ってのは「無」かなあ。 この辺のお話って、Synopsis だとどの辺にあるんだろうか。

■_

■_

偽サマータイム…

2011年07月01日

■_

なんか忘れているような気がするんだよなあ。

あ、今日、ついった経由で知ったのですが、Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages (Pragmatic Programmers) の翻訳本がそろそろ出るそうです。 とはいえ今週来週の話ではないようですけども。 7つの言語 7つの世界|Ohmsha

LL Planet の会場で僕と握手!(謎)

■_ 4.0

とりあえず素の状態でビルド。

>cd gawk-4.0.0

>copy pc
pc\ChangeLog
ChangeLog を上書きしますか? (Yes/No/All):
n
pc\ChangeLog.0
ChangeLog.0 を上書きしますか? (Yes/No/All)
: n
pc\config.h
pc\gawk.def
pc\gawkmisc.pc
pc\getid.c
pc\install.awk
pc\Makefile
pc\Makefile.tst
pc\mkinstal.sh
pc\popen.c
pc\popen.h
       10 個のファイルをコピーしました。

>make mingw32
make  all \
        CC=gcc O=.o CF="-O2 -gdwarf-2 -g3" OBJ=popen.o \
        LNK=LMINGW32 PLNK=PLMINGW32 DLNK=DLMINGW32 \
        LF="-gdwarf-2 -g3" LF2=-lmsvcp60 RSP=
make[1]: Entering directory `/cygdrive/c/Users/xxxx/yyyy/zzzz/gawk-4.0.0'
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  array.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  builtin.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  eval.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  field.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  floatcomp.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  gawkmisc.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  io.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  main.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  ext.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  msg.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  node.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  profile.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  re.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  replace.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  version.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  awkgram.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  getid.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  popen.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  getopt.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  getopt1.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  dfa.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  regex.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  random.c
gcc -gdwarf-2 -g3 -o gawk.exe array.o builtin.o eval.o field.o floatcomp.o gawkmisc.o io.o main.o ext.o msg.o node.o profile.o re.o replace.o version.o  awkgram.o getid.o popen.o getopt.o getopt1.o dfa.o regex.o random.o -lmsvcp60
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  eval_p.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  profile_p.c
echo array.o builtin.o eval_p.o field.o floatcomp.o gawkmisc.o io.o main.o > pgawk.rsp
echo ext.o msg.o node.o profile_p.o re.o replace.o version.o  >> pgawk.rsp
echo awkgram.o getid.o popen.o getopt.o getopt1.o dfa.o regex.o random.o >> pgawk.rsp
gcc -gdwarf-2 -g3 -o pgawk.exe array.o builtin.o eval_p.o field.o floatcomp.o gawkmisc.o io.o main.o ext.o msg.o node.o profile_p.o re.o replace.o version.o  getopt.o getopt1.o dfa.o regex.o random.o awkgram.o getid.o popen.o -lmsvcp60
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  debug.c
debug.c: In function `restart':
debug.c:2863: warning: passing arg 2 of `execvp' from incompatible pointer type
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  eval_d.c
gcc -c -O2 -gdwarf-2 -g3 -DGAWK -I. -DHAVE_CONFIG_H  command.c
echo array.o builtin.o debug.o eval_d.o field.o floatcomp.o gawkmisc.o io.o main.o > dgawk.rsp
echo ext.o msg.o node.o profile.o re.o replace.o version.o command.o  >> dgawk.rsp
echo awkgram.o getid.o popen.o getopt.o getopt1.o dfa.o regex.o random.o >> dgawk.rsp
gcc -gdwarf-2 -g3 -o dgawk.exe array.o builtin.o debug.o eval_d.o field.o floatcomp.o gawkmisc.o io.o main.o ext.o msg.o node.o profile.o re.o replace.o version.o command.o  getopt.o getopt1.o dfa.o regex.o random.o awkgram.o getid.o popen.o -lmsvcp60
make[1]: Leaving directory `/cygdrive/c/Users/xxxx/yyyy/zzzz/gawk-4.0.0'

警告が全然でないというのもなんかびっくり。 さてどこからいじるか。

■_ Worst practice

Perl ならでは。という気がする。 要は obsolete なもの一覧? 項目だけ抜き出し。

Perl Worst Practices - Blog - April 2011 - veekun: fuzzy notepad

Perl Worst Practices

April 13, 2011 at 08:15 PM

I hate to rank my own skill at anything, but if you forced me to, I'd say I'm pretty 
good at Perl. I get paid for it, at the very least. I've been around it a long time, 
and I know it well enough to tell you in intricate detail why I now use Python, 
instead.

But this is not that post. This post is about a particular wart of Perl: that it has a 
lot of warts. Large chunks of Perl are antequated, bug-prone, or outright obsolete. 
The trouble is that there are no warnings in the interpreter or documentation for many 
of these things, so a newcomer—or even an old-timer—won't know to avoid such pitfalls 
until told by someone else.

(略)

Forgetting use strict or use warnings

-w

Two-argument open()

goto LABEL

eval ""

eval {}

Backtics/qx or system() with one argument

foreach

C-style for

chop()

$_ outside microblocks

map and grep without a microblock

map $_ * 2, @numbers;

map { $_ * 2 } @numbers;

$|

select

Non-trivial, implicit return

new Object

Things you should not do without an extremely good reason

Rolling your own classes

wantarray

Disabling strict refs

Assigning to @_

Beginner mistakes

&foo()

for my $line (<$fh>)

@array[$i]

print $fh $data

■_

■_ あとでよむ

そういやあともう少しで完了という状態の浮動小数点数ネタがあったんだよな (自分で書いたものではなく訳しただけですが)。

research!rsc: Floating Point to Decimal Conversion is Easy

Floating Point to Decimal Conversion is Easy

Floating point to decimal conversions have a reputation for being difficult. At heart, 
they're really very simple and straightforward. To prove it, I'll explain a working 
implementation. It only formats positive numbers, but expanding it to negative numbers, 
zero, infinities and NaNs would be very easy.

(略)

Posted by rsc on Friday, July 01, 2011

Floating point to decimal conversion is not so easy | GNU Smalltalk

Floating point to decimal conversion is not so easy
By Paolo Bonzini - Posted on July 1st, 2011

Russ Cox of Plan-9 and Go fame posted a blog entry titled Floating Point to Decimal 
Conversion is Easy. While he is usually right, I believe this time he isn't.

Floating point to decimal conversion is easy if you are okay with ugly results. A good 
conversion routine will print the shortest decimal representation of the 
floating-point number, that is, the shortest decimal number whose closest 
floating-point representation equals the original number. You do not want 
0.30000000001, you want 0.3, because the number right above 0.3 is 0.30000000003 and 
0.30000000001 does not provide any extra precision.

Otherwise, your users will complain. (And you need to make sure you got it right, 
otherwise the will complain even more).

Here is how GNU Smalltalk does it. I'm pretty sure it is correct, too.

(略)

Copyright (C) Free Software Foundation, Inc. - Credits

GNU Smalltalk is part of the GNU Project.

Fexl
 Function EXpression Language

Fexl - a Function Expression Language

Fexl is a programming language based on pure functions.

The name "Fexl" (pronounced Fex' - il) stands for Function EXpression 
Language. It's an Accurate name, because Fexl is indeed a language for expressing 
functions. As you will see, everything in Fexl is a function.

The Basics of Fexl

RULE 1: EVERYTHING is a function.

This means everything, including data. A list is a function. A boolean value is a 
function. A number is a function. A string is a function. An entire program is a 
function. You name it, it's a function.

(略)

一つ前へ 2011年6月(下旬)
一つ後へ 2011年7月(中旬)

ホームへ


リンクはご自由にどうぞ

メールの宛先はこちらkbk AT kt DOT rim DOT or DOT jp