本書は「徒弟制度」をキーワードとして物事に習熟するための方法が記載されている。確かに「無知の受け入れ」と「適切なフィードバック」の繰り返しは大事だと思う。後は終わりが無いことを楽しむこと。
問題は「適切にフィードバックしてくれる環境と人」をどうすれば見つけることができるのか?運と度胸…。自分にはどちらも足りない。
Perl6はまだ様子見する。
そろそろかなとrakudo(#29)を触ってみた感想。もう少し待とう・・・。とりあえず触った事を記録。
試したのは加算器関数。まず、イメージで実装してみる。
sub make_adder($n) { {$n += $^i} } my $adder30 = make_adder(30); $adder30.(1).say; # 31になる $adder30.(5).say; # 36になる $adder30.(11).say; # 47になる
ブロックがどうのというエラーで動かない。make_adder関数の戻り値ブロックの表記がだめらしい。しかたがないので表記を変えてみる。
続きを読むPerlでDSL
『Rubyによるデザイン・パターン』を読み終えて内部DSLが分かった気になった。調子に乗ってPackRat*1をPerlに移植してみた。少しPerl風にアレンジ。
まず、内部DSLから。
# 内部DSL(backup.pr) backup { from => '/home/hoge/old1', to => '/tmp/backup', file_regx => '^.+\.(txt|doc)$', interval => 60, }; backup { from => '/home/hoge/old2', to => '/tmp/backup', file_regx => '^.+\.(mp3|wav)$', interval => 30, };
バックアップの定義を行っている。もちろん文法はPerlに従う。そして、内部DSLを実行する部分は次のとおり。
続きを読むRubyでチャーチ数
Rubyに慣れるとっかかりとしてチャーチ数を定義してみた。
lambdaで包まずに関数リファレンスを関数に渡す方法がわからない。。
# 数値(xに対するs関数の適用回数で数値を表す) def zero (s, x) x end def one (s, x) s[x] end def two (s, x) s[s[x]] end def three (s, x) s[s[s[x]]] end def four (s, x) s[s[s[s[x]]]] end def five (s, x) s[s[s[s[s[x]]]]] end # 足し算(m+n回だけxに対してs関数を適用する) def plus(m, n, s, x) m[s, n[s, x]] end n = plus( lambda{|s, x| five(s, x)}, lambda{|s, x| two(s, x)}, lambda{|n| n + 1}, 0) print "5 + 2 = ", n, "\n" # 掛け算(m*n回だけxに対してs関数を適用する) def multi(m, n, s, x) m[lambda{lambda{|x| n[s, x]}}.call(), x] end m = multi( lambda{|s, x| four(s, x)}, lambda{|s, x| three(s, x)}, lambda{|n| n + 1}, 0) print "4 * 3 = ", m, "\n"
実行すると次のようになる。
続きを読むPHPとファーストコンタクト
食わず嫌いだったPHP。触ってみると手に馴染みそうで良い。
早速、フィボナッチ数列に挑む。
<?php # 整数の無限リスト function stream($i) { return function() use (&$i) { return $i++; }; } # フィボナッチ数列の無限リスト function fibos() { $lazy = stream(0); $prevs = array(0, 0); return function() use ($lazy, &$prevs) { $now = $lazy(); if ($now == 0 || $now == 1) { $ans = $now; } else { $ans = $prevs[0] + $prevs[1]; } $prevs = array($prevs[1], $ans); return $ans; }; }
以前もやった遅延評価を使った。
続きを読むPerlで対話型コマンドの実行
前回はTeraTermマクロで対話型コマンドの実行をがんばった。けど扱いづらい。Perl使いたい。というわけで、telnetコマンドをfork/execしてpipeで標準入出力を操作してみた。*1 *2
まず、ファイルハンドルから値を読み込む関数と書き出す関数。読み出しでは応答が1秒間無かったら入力待ちと判断してる。*3
use strict; use warnings; use IO::Select; sub read_all { my ($stdout_r) = @_; my $read_line; my $s = IO::Select->new($stdout_r); while (1) { my @ready = $s->can_read(1); last if (@ready == 0); sysread($stdout_r, my $in, 1); $read_line .= $in; } return $read_line; } sub writeln { my ($stdin_w, $write_line) = @_; syswrite($stdin_w, "$write_line\n", length("$write_line\n")); }
次がtelnetをfork/execするtelnet関数。ログイン処理と終了処理も行う。*4 *5
*1:CPANが使えればNet::Telnet使うんだけどな・・・。
*2:直接対話型コマンドをfork/execしても良いけど、よりユーザ環境に近づけるためにtelnetを挟みたかった。
*4:exec失敗で固まったりバグだらけ。
*5:fork/execよりopen3関数を使うほうが簡潔だけど、今回はお勉強のためfork/exec
TeraTermマクロで対話型コマンドのテスト
定期的に行われる対話型コマンドの回帰テスト。バッチ化できないからって毎度手動でやるのはアホらしいよね。というわけで、TeraTermマクロでがんばってみる。
まずは簡単なテスト対象。
#include <stdio.h> int main() { int n = 0; do { printf("in => "); scanf("%d", &n); if (n == 1) { printf("Hello, world%d\n", n); } else { printf("error%d\n", n); } } while (n != 1); return 0; }
プロンプトを表示して入力を待つ。「1」を入力したらプログラムを終了する。入力値に応じて文字列を出力する。かなり手抜き。
そして、上記を実行するTeraTermのマクロ。
続きを読む