Io Languageでタイマー

Ioを使っていていつも思うのが、どうやってタイマーを実装するか。という問題

たとえば、3秒毎に特定の処理をしたくなった時、こんなコードを書いてしまいたくなる

1
2
3
4
5
6
7
loop (
  proc1
  proc2
  proc3
  :
  wait(3)
)

一見動いてしまうけど
でも、これは実はダメで loop でブロックされてしまうし、 wait 時にスレッドがブロックされてしまう

もうかれこれ3年くらい前に実装したものが↓
/lang/io/Timer – CodeRepos::Share – Trac

まぁ、なんとなく動くんだけど、System sleepwait は全体がブロックされてしまう問題があり 同時並行性に問題があった
(そもそも 0.01 sec で sleep してるあたりが問題すぎる)

ということで、これをどうにかして解決したいなぁ。と3年ぶりに思い至り Addon の Concurrency Thread でどうにか出来るんじゃないか。ということで、 non-blocking な実装を考えてみた

実装としては、親スレッドで 時間を受け取る Server を立ててしまって、子スレッドを生成して
その子スレッド内で sleep すれば親スレッドをブロックさせないという仕掛け

親スレッドはこんな感じに作っておいて

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Timer Interval Loop := Server clone do (
  setPort(11002)

  listener := Map clone

  addListener := method(id, callback,
    listener atPut(id, callback)
  )

  Handler := Object clone do (
    handle := method(socket, server,
      while(socket isOpen,
        if(socket read) then (
          data := socket readBuffer
          id := data beforeSeq(":")
          timestamp := data afterSeq(":")
          if(server listener hasKey(id)) then (
            callback := server listener at(id)
            callback @call(id, timestamp asNumber)
          )
        )
        socket readBuffer empty
      )
      socket close
    )
  )

  handleSocket := method(socket, Handler clone @handle(socket, self))
)

子スレッドはソケットで書き込んであげている

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
thread = Thread createThread("""
  id := "#{id}"
  host := "localhost"
  port := #{Timer Interval Loop port}
  interval := #{interval}

  socket := Socket clone
  socket setHost(host)
  socket setPort(port)
  socket connect

  if (socket isOpen) then (
    "client connected" println
  ) else (
    Exception raise("connection failed")
  )

  timestamp := Date now asNumberString
  msg := "\#\{id\}:\#\{timestamp\}"
  loop(
    timestamp := Date now asNumberString
    socket write(msg interpolate)
    wait(interval)
  )
""" interpolate)

まぁ、時間でブロックされずにコールバックをとれる javascript の setTimeoutsetInterval がすごいなぁ。ってのとそれをどうやって io で作ろうかなと思った奮闘記

Io Language で Yielding

とある言語で generator が入るらしいというのをみてしまった。
generator + yielding の仕組みらしい。なにそれ python。
(内部イテレータや外部イテレータについてはここでは触れない感じです。)

Generator + yield

ジェネレータは、僕の認識だと closure のような仕組みに yielding できるインタフェースを用意したものだと思ってる
それゆえ yielding で使う構文である yield さんを単体で使うというよりセットで使っているものが多そう

例えば、こんな感じのループとか

1
2
3
4
5
6
7
8
9
10
##### python
def gen():
  for i in range(10):
    print i
    yield

hoge = gen()
hoge.next() # => 0
hoge.next() # => 1
hoge.next() # => 2

なので、 yield 単体でも動きそうで動かない

1
2
3
4
5
6
7
8
9
def yielding():
  i = 0;
  while(1):
    i = i + 1
    print i
    yield

yielding()
yielding()

io での yield

IoLanguage における yield は、単なるコンテキストスイッチ(というか、キューイングされた次の処理の実行(シングルスレッドで実行されるtimerのような))に近い感じがしている

先ほど書いた python のコードは、io だと全然違う動きをする

1
2
3
4
5
6
7
8
9
10
11
12
13
14
yielding := block(
  for(i, 0, 3,
    i println
    yield
  )
)

yielding call()

// =>[results]
0
1
2
3

全然 yield してないです..
あくまで一つの処理を終えてから、次の処理に行こうとしてそうです。(yieldで止まらない)

ということで、呼び出し自体を非同期にする @ とか @@ を使います

1
2
3
4
5
6
7
8
9
10
11
12
13
14
yielding := block(
  for(i, 0, 3,
    i println
    yield
  )
)

yielding @@call
yield // async call を元処理に戻す
yield // 次の yield を呼び出す

// => [results]
0
1

loop でも使える

1
2
3
4
5
6
7
8
9
10
11
12
count := block(
  counter := 0
  loop(
    counter = counter + 1
    counter println
    yield
  )
)
count @call
yield // => 1
yield // => 2
yield // => 3

yield とひとくくりにしても、処理系によって意味合いが違うのがいいですね。
(Java とかの Thread#yield があったけど、大まか iolang のような意味合いだったよーな)

io でも Generator (actor)

さて、ここまで出来たのですが、 python の generator のように、外部イテレータ側に値を返したいです
そんなとき便利な actor

1
2
3
4
5
6
7
8
9
10
11
12
13
generator := method(
  counter := 0
  block(
    counter = counter + 1
  )
)

foo := generator
val_1 := foo @call
val_2 := foo @call

val_1 println // => 1
val_2 println // => 2

とりあえず、これで動きそう。もはや yield どこ行ったって感じだけど。
promise でもできそうです。

1
2
3
4
5
6
7
8
9
10
11
12
13
generator2 := method(next,
  counter := 0
  block (
    counter = counter + 1
    next(counter)
  )
)

foo := generator2(method(v, v println))
foo @@call
yield
foo @@call
yield

ここで yield 使ってるので、 @@ で呼び出したコルーチンを呼び戻すため
ということで、ここまで

Io Scope #1

今回は jsxについて ではなく、iolanguage の block と scope まわりについて少し

javascript の closure ってとても可読性が高くて、よくあるサンプルならこんな感じ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var createCounter = function (){
  var count = 0;
  return function (){
    return count++;
  };
};

var a = createCounter();
console.log(a()); // => 0
console.log(a()); // => 1

var b = createCounter();
console.log(b()); // => 0
console.log(b()); // => 1

んで、これを io でやろうとする場合、そのままやるならこんな実装になる

1
2
3
4
5
6
7
8
createCounter := method (
  count := 0;
  block ( count = count + 1 )
)

a := createCounter
a call println => 1
a call println => 2

と、method や block が入り組んだ、とても気持ち悪いコードになってしまう。
ただ、これはなんてことはない、javascriptのブロックがfunctionになっているから、綺麗なコードに見えるだけだ!(とかいう)
ちなみに、このコードを下記のように method だけにすると、スコープの参照が出来なくなってしまう

1
2
3
4
5
6
7
createCounter := method (
  count := 0;
  method ( count = count + 1 )
)

b := createCounter
b println => Exception: Object does not respond to 'count'

つまり、method は内包的なブロックを参照できないけど block は参照できる。と
んで、これを使うと interpolate がひと味違ってくる

1
2
3
4
a := block(a, b, c,
  "hello #{a} #{b + c}" interpolate
)
a call("hello world", 1, 2) // => hello hello world 3

interpolate は通常こんな使い方になってしまうんだけど、block はスコープを参照してるのがいいね

1
2
3
4
5
obj := Object clone
obj a := "hello world"
obj b := 1
obj c := 2
"hello #{a} #{b + c}" interpolate(obj) // hello hello world 3

さて、何を書こうと思ってたか忘れてしまった。。。
block とかその辺りは次回へ続く。。。

Io Language Assignment Code

今日は気分転換に io の話題でも
io-lang には3種類くらいの assignment statement(というか expressionかな)があるんだけど、
どれも使い方がよくわからん、と最初につまづくことかと思います。

代入式としては、以下の3つです

1
2
3
hoge := "set value"
hoge = "update value"
hoge ::= "new value"

と、これらはそれぞれ、以下のように動作します

1
2
3
4
5
6
Lobby setSlot("hoge", "set slot")
hoge println // => "set slot"
Lobby updateSlot("hoge", "update value")
hoge println // => "update value"
Lobby newSlot("hoge", "new value")
hoge println // => "new value"

んで、::= である、newSlot は setter を生成してくれるメソッドになります。

1
2
3
hoge := Object clone
hoge foo ::= 123
hoge setFoo(456)

こんな感じ。
今回は、この ::= の動作まわりではなく、:== についての話題です。
まずは、下記のコードをみてください

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
x := 10

hoge := method(
  x = 123
  ("hoge x is " .. x) println
)
foo := method(
  x := 456
  ("foo x is " .. x) println
)

hoge
("1) x is " .. x) println

foo
("2) x is " .. x) println

これの結果はどうなるでしょうか。
すべての x の出力は hoge メソッドで設定された 123 になるでしょうか。
それともスコープ上 一番上にある 10 のままになるでしょうか。

結果はこんな感じになります

1
2
3
4
hoge x is 123
1) x is 123
foo x is 456
2) x is 123

なんと、hoge メソッドで上書きした(updateSlot)値は foo メソッドで上書きされていない(setSlot)のです
少し不思議な動きな感じもします。

ただ、これも javascript で考えると案外フツーなことだったりします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var x = 10;

var hoge = function (){
  x = 123;
  console.log("hoge x is " + x);
};
var foo = function (){
  var x = 456;
  console.log("foo x is " + x);
};

hoge();
console.log("1) x is " + x);

foo();
console.log("2) x is " + x);

このjsのコードもioの結果と同じになります。

なんとなく、ioでもレキシカルスコープみたいのがあるんだなーと思うと夢が広がりングですね。 ちなみに、この話題は最近投稿された↓のトピックから参照してます。
iolanguage : Message: Re: [Io] Assignment Operators

その内、どこかで block と interpolate などについても話題にしたいところ。

My First Perl#5

さて、期間があいてしまいました。
クラス系をやっていたけど、少し脱線して、関数プログラミング的なものを少しやってました。
理解を深めるために、今回もjavascriptのコードを含めます。

高階関数

perlでも高階関数(関数を引数に受け取れる関数)を扱えるらしい。
記述としてはこんな感じ

1
2
3
4
5
6
7
8
9
10
11
12
13
use strict;
use warnings;

sub hoge {
  my ($foo, $a, $b) = @_;

  return &$foo($a, $b);
}

print hoge(sub {
  my ($x, $y) = @_;
  return $x + $y;
}, 3, 5);

これは javascript に置き換えるとこんな感じになる

1
2
3
4
5
6
7
var hoge = function(foo, a, b){
  return foo(a, b);
};

console.log(hoge(function (x, y){
  return x + y;
}, 3, 5));

幾分(というか、かなり)の部分で javascript の方が可読性が高いけど、
関数hogeは、第一引数に高階関数と引数a, b受け取る関数になる、
高階関数の実装は、与えられた引数x, yを加算するだけ、というシンプルなもの

perl のコードだと、&$foo となっているけど、$foo に入っているコードや文字列の実行に当たるらしい。
これに関しては以下になる

変数に与えられた関数の実行

変数に割り当てられた変数の実行は、こんな感じでできるらしい(ただし、”strict refs”になる)

1
2
3
4
5
6
7
8
sub hoge {
  my $arg1 = shift;

  print "arg1 => $arg1 \n";
}

my $variable = "hoge";
&{$variable}("hello world");

これにより、変数$variableに割り当てられた値の実行は &$variable で行うらしい

カリー化

高階関数ができるなら、やっぱり使えて欲しいカリー化(currying)
カレーじゃない方で

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
use strict;
use warnings;

sub currying {
  my ($target, $arg1, $arg2) = @_;

  return sub {
    my $arg3 = shift;

    return &$target($arg1, $arg2, $arg3);
  };
}

my $calc = sub {
  my ($a, $b, $c) = @_;

  return ($a + $b) * $c;
};

my $c1 = currying($calc, 1, 2);
print &$c1(3); # ==> 9
print &$c1(4); # ==> 12

my $c2 = currying($calc, 3, 4);
print &$c2(3); # ==> 21
print &$c2(4); # ==> 28

関数を返却されたことがわかっていれば、&$variable() で関数を実行できるらしい
これにより、引数束縛(curry)ができると。
少し、&$var が気持ち悪いけど。

これまた、js で書きなおすとこんな感じ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var currying  = function(target, arg1, arg2){
  return function(arg3) {
    return target(arg1, arg2, arg3);
  };
}

var calc = function(a, b, c) {
  return (a + b) * c;
};

var c1 = currying(calc, 1, 2);
console.log(c1(3)); // ==> 9
console.log(c1(4)); // ==> 12

var c2 = currying(calc, 3, 4);
console.log(c2(3)); // ==> 21
console.log(c2(4)); // ==> 28

クロージャの生成

少し戻り、クロージャの生成とその実行
高階関数ができるなら、やっぱり使えて欲しいクロージャ
やってみた。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use strict;
use warnings;

sub closure {
  my $counter = 0;

  return sub {
    return $counter++;
  };
}

my $c1 = closure();
print &$c1(); # ==> 0
print &$c1(); # ==> 1

my $c2 = closure();
print &$c2(); # ==> 0
print &$c2(); # ==> 1

# c1 
print &$c1(); # ==> 2

かなり素直に実行できます。

今回はここまで

次回は、リファクタリングで使える ::can とか使って
パッケージ単位で関数プログラミングです。

人はそれをメタプログラミングというらしいけど、関数言語だと結構頻繁に使えて便利なので
次回はそこにハマった人の内容になる。かも。

My First Perl #4

クラス編

ということで、クラス。
Classで重要なのはやっぱり継承パターンと多態性でしょう。
アクセサはどうなってるのか、パッケージとかも含め、それくらいできると夢が広がりングな気がする

参考にはいつもの オブジェクト指向 / Perl逆引き事典 - サンプルコードによるPerl入門 を 見てます。

クラス作成

package が使えるそうな。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use strict;
use warnings;

package Hoge;

sub new {
  my $proto = shift;
  my $self = {};

  bless $self, $proto;

  my $hoge = shift;
  $self->{hoge} = $hoge;
  return $self;
}

my $hoge = Hoge->new('hello world');
print $hoge->{hoge} . "\n";

コンストラクタの定義から、プロパティの設定と取得はこうやるのね。
元のページ → 汎用的なコンストラクタの雛形 - サンプルコードによるPerl入門 には init メソッドが必要とのことだったけど、今回は無視
どうやら、new のコンストラクタには [Class(prototype), arg1, arg2..] といった形式で渡されているようですね
bless がよくわからないけど、js でいうところの Function.prototype.bind 的なものだろうか、第一引数に prototype を割り当てる的な(それだとapplyの方が近そうだけど)

プロパティ作成

もう少し、プロパティ
参考元を参考に、引数を色々受け取ってみる

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
use strict;
use warnings;

package Hoge;

sub new {
  my $proto = shift;
  my $self = {};

  bless $self, $proto;

  $self->init(@_);

  return $self;
}

sub init {
  my ($self, ($hoge, $foo, $bar)) = @_;

  $self->{hoge} = $hoge;
  $self->{foo} = $foo;
  $self->{bar} = $bar;
}

my $hoge = Hoge->new('hello', 'world', 'perl #4');
# print $hoge->hoge . ':' . $hoge->foo . ':' . $hoge->bar . "\n";
## => Can't locate object method "hoge" via package "Hoge"
print $hoge->{hoge} . ':' . $hoge->{foo} . ':' . $hoge->{bar} . "\n";

なるほど、$self->{verialble} で設定したものは、$self->variableで取り出せないのね(Hashだから?)。当たり前といえば当たり前だった。
それ以外は意外とフツーな感じ

メソッド作成

プロパティまでは作成できたので、次はメソッド。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
use strict;
use warnings;

package Hoge;

sub new {
  my $proto = shift;
  my $self = {};

  bless $self, $proto;

  $self->init(@_);

  return $self;
}

sub init {
  my ($self, ($hoge, $foo, $bar)) = @_;

  $self->{hoge} = $hoge;
  $self->{foo} = $foo;
  $self->{bar} = $bar;
}

sub greeting {
  my $self = shift;

  print $self->{hoge} . ':' . $self->{foo} . ':' . $self->{bar} . "\n";
}

my $hoge = Hoge->new('hello', 'world', 'perl #4');
$hoge->greeting();

先ほどの property で出力してたのを メソッドで。
第一引数に self(自分自身) が入ってるとか、python ぽい

メソッド引数

メソッドのプロパティはどうなってるのか。
たぶん、#init で試したから同じだと思うけど。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
use strict;
use warnings;

package Hoge;

sub new {
  my $proto = shift;
  my $self = {};

  bless $self, $proto;

  $self->init(@_);

  return $self;
}

sub init {
  my ($self, ($hoge, $foo, $bar)) = @_;

  $self->{hoge} = $hoge;
  $self->{foo} = $foo;
  $self->{bar} = $bar;
}

sub greeting {
  my $self = shift;
  my ($arg1, $arg2, $arg3) = @_;

  print $self->{hoge} . ':' . $self->{foo} . ':' . $self->{bar} . "\n";
  print $arg1 . ',' . $arg2 . ',' . $arg3 . "\n";
}

my $hoge = Hoge->new('hello', 'world', 'perl #4');
$hoge->greeting('a', 'b', 'c');

ふむ。
shift は @_ から一つ shift して、 @_ 自体は (a, b) = @_ とかのリスト構文的なので、値をまとめて代入できる。と

継承

クラスの継承。なんかちょっと特殊だった

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use strict;
use warnings;

package Hoge;

sub new {
  my $proto = shift;
  my $self = {};

  bless $self, $proto;

  $self->init(@_);

  return $self;
}

sub init {
  my ($self, ($hoge, $foo, $bar)) = @_;

  $self->{hoge} = $hoge;
  $self->{foo} = $foo;
  $self->{bar} = $bar;
}

sub greeting {
  my $self = shift;
  my ($arg1, $arg2, $arg3) = @_;

  print $self->{hoge} . ':' . $self->{foo} . ':' . $self->{bar} . "\n";
  print $arg1 . ',' . $arg2 . ',' . $arg3 . "\n";
}

package Foo;
use base('Hoge');

sub new {
  my $proto = shift;
  my $self = {};

  bless $self, $proto;

  $self->init(@_);

  return $self;
}

sub greeting {
  my $self = shift;

  print 'Im Foo#' . $self->{hoge} . ',' . $self->{foo} . "\n";
}

my $foo = Foo->new('hello', 'world', 'perl #4');
$foo->greeting('a', 'b', 'c');

まず、

  • @ISA はよくわからなかったので、use baseによる継承を使った。
  • super を指定しないでも上位メソッドはコンストラクタから呼べた
  • new のコンストラクタには、上位クラスの参照はなかった
  • override 記述をしなくても、自動的に override だった。
  • 上位プロパティは特に指定なしに呼び出せた。

これ、use で複数とか指定するとどうなっちゃうんだろ。差分継承だったらいいな。(それはいつかやる)

overrideしたメソッドから上位メソッドの呼び出し

疑問に思ったのでこれをやってみる
この方法は、ここから 参照。
ちなみに、やらんとしてることは、javascript だとこんな感じ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var Hoge = function(a, b) {
  this.a = a;
  this.b = b;
};
Hoge.prototype.greeting = function (){
  console.log('Im Hoge: ' + this.a + ',' + this.b);
};

var Foo = function(){
  Hoge.apply(this, arguments);
};
Foo.prototype.greeting = function(bar){
  Hoge.prototype.greeting.apply(this, arguments);
  console.log('bar value => ' + bar);
};

var foo = new Foo('hello', 'world');
foo.greeting('**bar value**');

ということで、perl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use strict;
use warnings;

package Hoge;

sub new {
  my $proto = shift;
  my $self = {};

  bless $self, $proto;

  $self->init(@_);

  return $self;
}

sub init {
  my ($self, ($hoge, $foo, $bar)) = @_;

  $self->{hoge} = $hoge;
  $self->{foo} = $foo;
  $self->{bar} = $bar;
}

sub greeting {
  my $self = shift;
  my ($arg1, $arg2, $arg3) = @_;

  print $self->{hoge} . ':' . $self->{foo} . ':' . $self->{bar} . "\n";
  print $arg1 . ',' . $arg2 . ',' . $arg3 . "\n";
}

package Foo;
use base('Hoge');

sub new {
  my $proto = shift;
  my $self = {};

  bless $self, $proto;

  $self->init(@_);

  return $self;
}

sub greeting {
  my $self = shift;

  $self->SUPER::greeting('Im', 'Foo', '#greeting');
}

my $foo = Foo->new('hello', 'world', 'perl #4');
$foo->greeting('a', 'b', 'c');

なるほど。$self->SUPER::#method で上位メソッド(というか親インスタンスのメソッドの呼び出し)ができるようになるのね。
これは使い道が広がるわ。

次回

アクセサを見てみたいところだけど、やっぱここで触れなかった package あたり。 どうやって分割してんのかと。

My First Perl #3

ということ(?)で、関数とクラスあたりのステップに行こうと思う

関数

関数は sub を使う。と
しかも sub が sub たる理由はサブルーチン。なるほど。

1
2
3
4
5
6
7
8
9
use strict;
use warnings;

sub hoge {
  my $arg1 = shift;
  print $arg1 . "\n";
}

hoge('hello world');

shift に引数はないけど、引数を先頭から取得するときに使うらしい。
少し謎。
どうやら shift の引数なしは shift @_ と同義らしい http://d.hatena.ne.jp/perlcodesample/20101130/1298764341

もう少し引数を受け取りましょう。
構造体Hashとか

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
use strict;
use warnings;

#my %hoge = (a => 1, b => 2);
# HashをHashとして出力するときは %hash なのね。。
#print %hoge . "\n";
# でもkeyの値を出すときは $hash なのね。。
#print $hoge{a} . "\n";

sub foo {
  my $value_1 = $_[0];
  print $value_1 . "\n";
  # ==> a と出る

  my $value_2 = ref $_[0];
  print $value_2 . "\n";
  # ==> 何もでない

  my $value_3 = ref {@_};
  print $value_3 . "\n";
  # ==> Hash と出る...ということはこれでHashを受け取れたハズ。

  #print $value_3{a} . "\n";
  # ==> 'Global symbol "%value_3" requires explicit package' えええええ!

  #my %value_4 = ref {@_};
  #print $value_4{a} . "\n";
  # ==> 'Odd number of elements in hash assignment' えええええええええ!!

  # 素直に。。
  my %value_5 = @_;
  print $value_5{a} . "\n";
  print $value_5{b} . "\n";
}

foo((a => 1, b => 2));

最初に http://d.hatena.ne.jp/perlcodesample/20101130/1298764341 を読んだのがマズかったか。。。
やっぱりサンプルコードがあるほうがいいよね。
というっことで、 $value_(1..4) あでは、上記の記事をナナメ読みして頑張った結果。
$value_5 というフツーな方法で大丈夫だと知ったのは http://d.hatena.ne.jp/perlcodesample/20080605/1212675666 の記事を読んでから。。

正直 $value_3{a} と $value_4{a} がエラーになる理由が全然少しもわからん
構文から学ぶべきだった。。。

perl って、%だったり $とか @とか タイヘンです。。

今回は sub 、もといサブルーチンに衝撃を受けたので、次回にでもクラスをやろう。。

Node.jsでコンソールにBad Apple!!を出力してみた

【東方】Bad Apple!! PV【影絵】 というニコニコ動画で人気の動画があるんだけど、これをコンソールに出してみよう。と思ってやってみた。

元の動画はモノクロな感じなので、コンソールに出力するのは簡単かなーと思っていたんだけど
案外面倒だった。

まず、元の動画をBitmapイメージシーケンスに変換するのが面倒だった。 MPEG Streamclip っていうソフトに行き着くまでが大変だった。。。
こんな感じで白黒なBitmapの連続データに変換してます。

んで、ここから連続したBitmap画像データができたので

このBitmapたちをjavascriptで読めるように nowelium/node-bitmap を作った。

Bitmapの読み取りは bmp ファイルフォーマットWindows bitmap - Wikipedia を参考にしてます。
Bitmapって画像データだけの塊だと思ってたら、ちゃんとした仕様があったんだね。。

今回の動画で使ってる実際のコードはgistに貼ってます。

話は戻るけど、本家の 【東方】Bad Apple!! PV【影絵】 の派生動画が色々面白くて

僕が今回これをつくろうと思うきっかけになった、Japanino(arduino互換機)でBad AppleしてたりUSBモニタに出してたりminecraftでやってたりとまぁ色々挑戦するのが面白い動画になってます。

そして、僕がBitmapと格闘している間、世の中はPNGでWebsocketsまでやっていたのだった。。。
WebSocket で PNG 画像をバイナリ転送して、JavaScript で展開して表示してみた
僕の実装の方はコンソールで動画が見れるよ!っていう誰得なものだから実用性が欲しい。。 ここまで実装できたし、次はsocket.ioにでも乗っけてみると面白そうだ。

My First Perl #2

前回の続き

for 文がダサいとか言いながら、配列の初期化にこんなのを使ってた。

1
2
3
4
my @list = ();
for(my $i = 0; $i < 100; ++$i){
  push @list, $i;
}

これは、perl の範囲演算子で何とかなった。

1
2
3
4
5
use strict;
use warnings;

my @list = (0 .. 100);
print $_ . "\n" for @list;

ということで、fizzbuzz 書き直し

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use strict;
use warnings;

my @list = (0 .. 100);

my @fizzbuzz = map {
  if(0 == ($_ % 3) && 0 == ($_ % 5)){
    "FizzBuzz"
  } elsif (0 == ($_ % 3)){
    "Fizz"
  } elsif (0 == ($_ % 5)){
    "Buzz"
  } else {
    $_
  }
} @list;

print $_ . "\n" for @fizzbuzz;

ということは、更に短くできそう

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use strict;
use warnings;

print $_ . "\n" for map {
  if(0 == ($_ % 3) && 0 == ($_ % 5)){
    "FizzBuzz"
  } elsif (0 == ($_ % 3)){
    "Fizz"
  } elsif (0 == ($_ % 5)){
    "Buzz"
  } else {
    $_
  }
} (0 .. 100);

おお。
後置 for で map が扱えるとか。ちゃんとした言語だ。
ということで、変数が $_ だけになったのが良くなってきた感じ。

FizzBuzz はこのくらにして、次へ

My First Perl #1

人生初 perl を書いていこうと思います。
頑張るぞ

教材は サンプルコードによるPerl入門 より

perl 自体は lion に入ってたものをそのまま

> perl -v

This is perl 5, version 12, subversion 3 (v5.12.3) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)

Copyright 1987-2010, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

control flow

Perl基礎文法最速マスター を参考にするのでスキップ

fizzbuzz

まずは、やっぱりこれで。
文法を読んだだけなので、エレガントさには欠ける予定

ルール

http://d.hatena.ne.jp/keyword/FizzBuzz より

3と5の公倍数の時は、FizzBuzzとだけ回答するべき。最初の定義では、たとえば15がやってきた時「3の倍数なのでFizzと言う、5の倍数なのでBuzzと言う、3と5の公倍数なのでFizzBuzzと言う、結果、15の時はFizzBuzzFizzBuzzになる」と解釈することも可能である。

定義

  • カウンターを設定、0とする。
  • カウンターに1を加える。
  • カウンターが100(の他、設定した値)を超えたなら、終了する。
  • カウンターが3と5の公倍数であるならば、「FizzBuzz」を出力し、2に戻る。
  • カウンターが3の倍数であるならば、「Fizz」を出力し、2に戻る。
  • カウンターが5の倍数であるならば、「Buzz」を出力し、2に戻る。
  • カウンターの数字を出力し、2に戻る。

実装

こんな感じ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use strict;
use warnings;

for(my $i = 0; $i < 100; ++$i){
  if((0 == ($i % 3)) && (0 == ($i % 5))){
    print "FizzBuzz\n";
  } elsif(0 == $i % 3){
    print "Fizz\n";
  } elsif(0 == $i % 5){
    print "Buzz\n";
  } else {
    print $i . "\n";
  }
}

うむ。正解かどうかわからん。
phpの文法は perl からパクったらしいので、古く慣れ親しんだ php でも描いてみた。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

for($i = 0; $i < 100; ++$i){
  if((0 == ($i % 3)) && (0 == ($i % 5))){
    print "FizzBuzz\n";
    continue;
  }
  if(0 == $i % 3){
    print "Fizz\n";
    continue;
  }
  if(0 == $i % 5){
    print "Buzz\n";
    continue;
  }
  print $i . "\n";
}

うむ。 else区を書きたくない派(あるのか?)の一員としては、単純なループならcontinue使いたくなります。

もう少し凝ってみよう

やっぱり for 文はダサさが目立つので map 文(?) とか 後置文(?) を使ってみたい

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use strict;
use warnings;

my @list = ();
for(my $i = 0; $i < 100; ++$i){
  push @list, $i;
}

my @fizzbuzz = map {
  if(0 == ($_ % 3) && 0 == ($_ % 5)){
    "FizzBuzz"
  } elsif (0 == ($_ % 3)){
    "Fizz"
  } elsif (0 == ($_ % 5)){
    "Buzz"
  } else {
    $_
  }
} @list;

print $_ . "\n" for @fizzbuzz;

配列アクセスは変数として $ を使うけど、配列としてのアクセスは @ を使うのね。
変数が配列なのかどうかが分かりやすいね。この言語。

ただ、 map の戻りを指定するのは、評価された値になるってとこがなんとも。他の式と違うんだね
あとは、map の結果は必ず配列になるハズなのに my @fizzbuzz って宣言するのはなんとも。。。

おわり

次行ってみよう