メタプログラミングRuby 五日目を読んだ

  • クラス拡張ミックスイン

で Perl6 だと

  • 普通にRole かなぁ?
    • attr_checked メソッドを生やす
    • add_method で適当にアクセサを作る
    • store する場所はぶっちゃけ,独立したattribute じゃなくてもいいよね.

メタプログラミングRuby
Paolo Perrotta
アスキー・メディアワークス
売り上げランキング: 5690

メタプログラミングRuby 二日目を読んだ

Module#method_missing() と define_method(), Object#send() あたり.

AUTOLOAD(=CANDO) と 動的定義か.

multi CANDO (MyPackage, $type, $name, *%args --> Container) { ... }

my $name = '&' . 'aaa';
::<$name> = method { ... }

みたく,CANDO とか動的定義でできそうだけど,
そもそもCANDO は呼ばれないような…
まだ実装されてないのかねぇ.*1
動的定義もできない?
あと eval 以外にできるのかな?

(2011/02/20 追記)
動的定義は,add_method を使えばいいのか.

メタプログラミングRuby
Paolo Perrotta
アスキー・メディアワークス
売り上げランキング: 5690

*1:Indirect name lookups not yet implemented だから?

メタプログラミングRuby 一日目を読んだ

まとめを抜粋

  • オブジェクトは複数のインスタンス変数とクラスへのリンクで構成されている.
  • オブジェクトのメソッドはオブジェクトのクラスに住んでいる(クラスから見れば,それはインスタンスメソッドと呼ばれる)
  • クラスはClass クラスのオブジェクトである.クラス名は単なる定数である.
  • Class はModule のサブクラスである.モジュールはメソッドを集めたものである.クラスはnew() でインスタンス化したり,superclass()で階層構造を作ったりできる.
  • 定数はファイルシステムのようにツリー上に配置されている.モジュールやクラスの名前がディレクトリ,通常の定数がファイルのようになっている
  • クラスはそれぞれBasicObject まで続く継承チェーンを持っている.
  • メソッドを呼び出すと,Ruby はレシーバのクラスに向かって一歩右へ進み,それから継承チェーンを上へ向かって進んでいく.メソッドを発見するか継承チェーンが終わるまでそれは続く.
  • クラスがモジュールをインクルードすると,そのクラスの真上の継承チェーンにモジュールが挿入される.
  • メソッドを呼び出すとき,レシーバが self になる.
  • モジュール(あるいはクラス)を定義するとき,モジュールが self になる.
  • インスタンス変数は常に self のインスタンス変数とみなされる.
  • レシーバを明示的に指定せずにメソッドを呼び出すと,self のメソッドだとみなされる.
#!/usr/bin/env perl6
# -*- mode: perl; coding: utf-8-unix; -*-

use v6;

class MyClass {
    has $!v;
    method my_method {
    }
}

my $obj = MyClass.new

say MyClass.WHAT; #=> MyClass()
say $obj.^parents.perl; # => (Any, Mu)
say $obj.^methods(:local).map({.name}).perl; #=> ("my_method")

メソッドサーチ,継承関係について,もうちょっと調べる必要があるな.

  • REPL 便利
  • .perl が inject 的に使える.p 的なものもある?
  • ^XXXX と HOW.XXXX を使う
  • class base と prototype base の両方が使える

メタプログラミングRuby
Paolo Perrotta
アスキー・メディアワークス
売り上げランキング: 41489

ホストOS からゲストOS(Windows XP) にssh する

ゲストOS

  • cygwin をインストールする.
  • openssh をインストールする.
  • ssh-host-config する.(基本yes)
  • /etc/sshd_config で,PasswordAuthentication no, ChallengeResponseAuthentication no する
  • CYGWIN sshd を,起動する (cygrunsrv -S sshd)
  • .ssh に id_rsa, authoried_keys とかを適宜置く.
  • ssh localhost - ローカルからssh できることを確認
  • Windowsファイアウォールで,22 ポートを開く

ホストOS 側で

# pcnet or e1000 かも
$ VBoxManage setextradata vm1 VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/Protocol TCP
$ VBoxManage setextradata vm1 VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/GuestPort 22
$ VBoxManage setextradata vm1 VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/HostPort 10022

ゲストのVMの再起動が必要.(OS の再起動じゃなくてもいい?)
VBoxManage startvm "vmname"

参考

rakudo コンパイルする

MacPorts をアップデートした所為か,昔コンパイルしたバイナリが動かなくなってたので,
clean したかったけど,よくわからんかったので全消ししてもっかいコンパイルしてみたメモ.

$ git clone http://github.com/rakudo/star.git rakudo-star
$ cd rakudo-star
$ make VERSION=2010.12 2> m.err | tee m.log
$ cd rakudo-star-2010.12
$ perl Configure.pl --gen-parrot 2> c.err | tee c.log
$ make 2> m.err | tee m.log
$ make rakudo-test 2> mt.err | tee mt.log
$ make install
$ ./perl6 -v

This is Rakudo Perl 6, version 2010.12 built on parrot 2.11.0Null PMC access in get_bool()
current instr.: 'perl6;Perl6;Compiler;version' pc 326881 (src/gen/perl6-grammar.pir:0)
called from Sub 'perl6;PCT;HLLCompiler;command_line' pc 1855 (compilers/pct/src/PCT/HLLCompiler.pir:917)
called from Sub 'perl6;Perl6;Compiler;main' pc 326820 (src/gen/perl6-grammar.pir:16982)
[1]    33934 exit 1     ./perl6 -v

ということで,やりながら気付いたけど,
make VERSION= すれば全部消さなくても良かったかもな.と思った.

(2011/02/16追記)
で,後で気付いたんだけど,parrot の tar を消さないと更新されないので注意.
*1

*1:しばらく parrot-2.1 とか使ってたよ…

メタプログラミングRuby を読み始めた

Ruby の知識は全然足りない状態で読み始めた.
とりあえず,色々調べながらで最初全然進めない感じですよ.

調べたこと - Ruby

  • Rakefile - test target を簡単に刺す
  • Rakefile - default ターゲットの指定方法

gist にしようかと思ったけど,とりあえずそのまま貼る
構成としては,

Rakefile
lib/object_model/alphanumeric.rb
test/test_object_model_alphanumeric.rb

Rakefile

require 'rake/testtask'

Rake::TestTask.new

task :default => "test"

こんな感じ.

で,Perl で書き直してみた.

Makefile.PL
lib/ObjectModel/Alphanumeric.pm
t/ObjectModel_Alphanumeric.t

Makefile.PL

use inc::Module::Install;

name 'ObjectModel-Alphanumeric';
all_from 'lib/ObjectModel/Alphanumeric.pm';

WriteAll;

lib/ObjectModel/Alphanumeric.pm

package ObjectModel::Alphanumeric;

use strict;
use warnings;

# Perl5 は,そもそもネイティブなオブジェクト指向言語ではないので
# autobox を使って,スカラにメソッドを刺せるようにする
sub to_alphanumeric {
    ($_ = shift) =~ s/[^\w\s]//g;
    $_;
}

1;

t/ObjectModel_Alphanumeric.t

#!/usr/bin/env perl

use strict;
use warnings;

use Test::More;
use FindBin;
use lib qq|$FindBin::Bin/../lib|;

use ObjectModel::Alphanumeric;
use autobox SCALAR => 'ObjectModel::Alphanumeric';

is(ObjectModel::Alphanumeric::to_alphanumeric('#3, the *Magic, Number*?'), '3 the Magic Number');
is('#3, the *Magic, Number*?'->to_alphanumeric(), '3 the Magic Number');

done_testing;

ということで,とりあえず Rakefile, Makefile.PL を書く辺で止まっているけど,
順番にやっていこうと思う.

参考

メタプログラミングRuby
Paolo Perrotta
アスキー・メディアワークス
売り上げランキング: 24616

Redmine で gitolite のリポジトリを扱いたい - 現状の確認

Redmine の lib/redmine/scm/adapters/git_adapters.rb を見ると,
基本的には,git コマンドで --git-dir 指定をして使っているような気がする.

$ egrep 'cmd = ' lib/redmine/scm/adapters/git_adapter.rb|perl -pe 's/^\s+//'
cmd = "#{GIT_BIN} --git-dir #{target('')} branch --no-color"
cmd = "#{GIT_BIN} --git-dir #{target('')} tag"
cmd = "#{GIT_BIN} --git-dir #{target('')} ls-tree -l "
cmd = "#{GIT_BIN} --git-dir #{target('')} log --no-color --date=iso --pretty=fuller --no-merges -n 1 "
cmd = "#{GIT_BIN} --git-dir #{target('')} log --no-color --raw --date=iso --pretty=fuller "
cmd = "#{GIT_BIN} --git-dir #{target('')} diff --no-color #{shell_quote identifier_to} #{shell_quote identifier_from}" 
cmd = "#{GIT_BIN} --git-dir #{target('')} show --no-color #{shell_quote identifier_from}"
cmd = "#{GIT_BIN} --git-dir #{target('')} blame -p #{shell_quote identifier} -- #{shell_quote path}"
cmd = "#{GIT_BIN} --git-dir #{target('')} show --no-color #{shell_quote(identifier + ':' + path)}"

git の --git-dir オプションは,ローカルリポジトリの .git ディレクトリを指定して,
カレントディレクトリじゃない場所に対してコマンドを実行するものと思えばいい.*1

なので,一応パスから変換して,ローカルのファイルシステムに git clone するようにすれば,
リモートリポジトリを指定して対応できるような気がするけど,
現状はそうなってないのかな?

テストが,test/unit/lib/redmine/scm/adapters/git_adapter_test.rb にあるようだ.
なんか,この辺を要求されたりした.

$ gem install mocha
$ gem install edavis10-object_daddy
$ gem install -v=2.10.3 shoulda

参考

で,target() とかは,lib/redmine/scm/adapters/abstract_adapter.rb を読む流れか.

とりあえず,git clone --mirror すれば,bare リポジトリができるので,
git fetch をcron すれば一応できることは確認できた感じ.
hook かけるのかなー.

*1:bare リポジトリだと使えない?