Perl6からGoの関数をつかう → はやい?

# はじめに

「[RubyからGoの関数をつかう → はやい](http://qiita.com/grj_achm/items/679b3f3af2cf377f0f02)」に便乗して、Perl6でShared Libraryを利用する方法を書きます。
釣りタイトルっぽくなってしまって恐縮です…

# あわせて読みたい

| 言語 | リンク | 説明 |
| :------ | :------ | :------ |
| Ruby+Go | [RubyからGoの関数をつかう → はやい](http://qiita.com/grj_achm/items/679b3f3af2cf377f0f02) | 元ネタ。再帰を使ったフィボナッチ数算出を例にRubyからのShared Libraryの使用を解説。論旨は各言語それぞれの得意分野を活かした使い方をしようというもの|
| Crystal | [Crystalで書く → はやい](http://qiita.com/etmnk/items/2801cd09c6ec4439c8fd) | 元ネタのRubyコードをCrystalでビルドして実行すればGoと遜色のない速度であったという検証記事|
| Ruby+Rust | [RubyからRustの関数をつかう → はやい](http://qiita.com/rejasupotaro/items/2aa57a67f4a97101950c) |
| Ruby | [RubyからGoの関数をつかわなくても再帰をやめる → はやい](http://mattn.kaoriya.net/software/20151106194958.htm) | 再帰を使わなければ速い旨 |
| Ruby | [Ruby で書く→速い](http://qiita.com/akaneko3/items/b909d51826597b9ec604) | 同上 |
| Common Lisp | [Common Lispで書く→はやい](http://qiita.com/bori_so1/items/16b5e0e2d61e6b897fca) | |
| Node.js | [Node.jsをつかう → はやい](http://qiita.com/ukiuni@github/items/3a5e8681edf2cdf1b54c) |
| JRuby+Scala | [JRubyからScalaの関数をつかう → はやい](http://qiita.com/Peranikov/items/42363adbb214b96a8278) | |
| Groovy+Go | [GroovyからGoの関数を使う→はやい](http://qiita.com/yujiorama_at_github/items/3f7cab906969764cc805) | |
| PHP+Go | [PHP から Go の関数を呼び出す](http://qiita.com/masakielastic/items/09018646d7d34996190a) | |


# 環境

|項目|値|
|:--------|:--------|
| ハード | MacBook Air (13-inch, Mid 2011) |
| OS | OS X El Capitan (10.11.1)|
| プロセッサ | 1.8 GHz Intel Core i7 |
| メモリ | 4 GB 1333 MHz DDR3 |

```
$ go version
go version go1.5.1 darwin/amd64

$ ruby -v
ruby 2.0.0p645 (2015-04-13 revision 50299) [universal.x86_64-darwin15]

$ perl6 -v
This is perl6 version 2015.09 built on MoarVM version 2015.09
```

### ①Perl6からGoの関数を呼ぶ。

1. 元ネタの「[Goを共有ライブラリにする](http://qiita.com/grj_achm/items/679b3f3af2cf377f0f02#go%E3%82%92%E5%85%B1%E6%9C%89%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AB%E3%81%99%E3%82%8B)」の通り、`fib.so`を作成します。

1. 共有ライブラリとしてコンパイルしたGoをPerl6から扱うには`NativeCall`モジュール[^nc]を使用します。

```perl:go-fib.pl
use v6;
use NativeCall;

sub fib(int32) returns int32 is native('./fib.so') { * }

say fib 40;
```

### ②再帰を使ったフィボナッチ数算出

```perl:fib_recursive.pl
use v6;

proto fib (Int $n --> Int) is cached {*}
multi fib (0)  { 0 }
multi fib (1)  { 1 }
multi fib ($n) { fib($n - 1) + fib($n - 2) }

say fib 40;
```

### ③再帰を使わないフィボナッチ数算出

```perl:fib_infinite_list.pl
use v6;

my constant @fib := 0, 1, *+* ... *;
say @fib[40];
```

### 結果

```bash:出力
# ① Perl6 with GO
$ time perl6 fib-go.pl
102334155

real	0m1.985s
user	0m1.867s
sys		0m0.076s
```

```bash:出力
# ② 再帰を使う
$ time perl6 fib_recursive.pl
102334155

real	0m0.301s
user	0m0.248s
sys		0m0.038s
```

```bash:出力
# ③ 再帰を使わない
$ time perl6 fib_infinite_list.pl
102334155

real	0m0.278s
user	0m0.237s
sys		0m0.036s
```

# おわりに

(この例だと遅くなってしまいましたが)
元記事にもあった通り、各言語の得意分野で適宜書き分けて利用すると良いと思います。

おわりです。

# 注釈と参考

[^nc]: [NativeCall](https://github.com/jnthn/zavolaj/blob/master/lib/NativeCall.pm6)

* [The Perl 6 Programming Language](http://perl6.org/#samp-fib)
* [Fibonacci sequence](http://rosettacode.org/wiki/Fibonacci_number#Perl_6)
* [Operators](http://doc.perl6.org/language/operators#infix_%3A%3D)
* [C_bindings.pdf](https://archive.fosdem.org/2015/schedule/event/c_bindings_a_journey/attachments/slides/723/export/events/attachments/c_bindings_a_journey/slides/723/C_bindings.pdf)