p6docを無理やり動かした話

# 最初に

題の通り、homebrewでインストールしたrakudo-star[^rakudo]で一緒に入ってくる`p6doc`がうまく動かせなかったので無理やり動かしたという個人的な記録です。

最新版のソースをgithubから持ってくるのが正解ですので真似しないでください[^yoiko]

## 概要

2015年のクリスマスにPerl6が正式リリースされるのが楽しみですね。

さて、Perl5でドキュメントを参照するコマンドは`perldoc`ですが、
Perl6では`p6doc`というらしいです。

## まずは、関数のドキュメントを参照する方法

```bash
# Perl5では
$ perldoc -f  SomeBuiltinFunction

# Perl6では
$ p6doc -f  SomeMethod
```

`f`はファンクションの`f`ですね。わかりやすい。

そして、`p6doc -f`を使うためには`p6doc-index build`でインデックスを作らないとか。さっそくやってみま

```bash
$ p6doc-index build
Type check failed in binding; expected 'Positional' but got 'Seq'
  in sub MAIN at /usr/local/bin/p6doc-index:35
  in block <unit> at /usr/local/bin/p6doc-index:76
```

うわあああしょっぱなからつまづいたぁぁぁぁぁ(動揺)

## `p6doc-index build`が動かない？

大丈夫。既知[^tot]の事象[^p6doc-index]です。

[変更点は一行だけみたい](https://github.com/perl6/doc/commit/5c4ca1a06da1e558c769ca0abf29448433c74f18)なので、手作業で直しちゃいましょう。(だめです)

`/usr/local/bin/p6doc-index`はウチの環境だと`/usr/local/Cellar/rakudo-star/2015.09/bin/p6doc-index`からのシンボリックリンクなので、後者を書き換えます。

```bash
# 念のため手元にバックアップ。
$ cp -i /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc-index ~/.p6doc-index.backup

# パーミッション555だと変更できないので、一旦755にします。
$ chmod 755 /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc-index

# 前述のコミットの通りファイルを書き換え。
$ vi /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc-index
## (ゴニョゴニョ)

# パーミッションを755に戻します。
$ chmod 555 /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc-index
```

```diff
# 手元にとったバックアップと比較して、変更点を確認。
$ diff -u .p6doc-index.backup /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc-index
--- .p6doc-index.backup	2015-11-20 23:08:00.000000000 +0900
+++ /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc-index	2015-11-20 23:11:31.000000000 +0900
@@ -32,7 +32,7 @@
         next unless $lib_path.e;

         $lib_path = $lib_path.Str;
-        my @files :=  find(:dir($lib_path),:type('file'));
+        my @files =  find(:dir($lib_path),:type('file')).map({.IO});

         for @files -> $f {
             my $file = $f.path;
```

さっき失敗したインデックスを作成してみます。

```bash
$ p6doc-index build

#=> 動きました！(成功すると何も表示されない)
```

では、`p6doc-index build`でインデックスも作ったことですし、
あらためて`Array`クラスの`push`メソッドについて調べ

```bash
$ p6doc -f Array.push
===SORRY!===
Cannot invoke this object (REPR: Uninstantiable)
```

う、うわあああああああああああ（椅子から転げ落ちる）

## `p6doc`が動かない？

落ち着いていこう。まだあわてるような時間じゃない。これもまた既知の事象[^p6doc]です。

[変更点は五行だけみたい](https://github.com/perl6/doc/commit/cbd940329c)なので、手作業で直しちゃいましょう。(錯乱)

`/usr/local/bin/p6doc`はウチの環境だと`/usr/local/Cellar/rakudo-star/2015.09/bin/p6doc`からのシンボリックリンクなので、後者を書き換えます。

```bash
# 念のため手元にバックアップ。
$ cp -i /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc ~/.p6doc.backup

# パーミッション555だと変更できないので、一旦write権加えます。
$ chmod +w /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc

# 前述のコミットの通りファイルを書き換え。
$ vi /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc
## (ゴニョゴニョ)

# パーミッションを755に戻します。
$ chmod -w /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc
```

```diff
# 手元にとったバックアップと比較して、変更点を確認。
$ diff -u .p6doc.backup /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc
--- .p6doc.backup	2015-11-20 23:15:13.000000000 +0900
+++ /usr/local/Cellar/rakudo-star/2015.09/bin/p6doc	2015-11-21 16:56:07.000000000 +0900
@@ -27,17 +27,17 @@
 }

 sub search-paths() {
-    (findbin()  X~ <../doc/perl6/lib/ ../lib/> X~ '',<Type/ Language/ Routine/>),
-    @*INC.map({CompUnitRepo.new($_)})».IO».Str.map({ /\/$/ ?? $_ !! $_ ~ '/' });
+    ((findbin()  X~ <../doc/perl6/lib/ ../lib/> X~ <Type/ Language/ Routine/>).list,
+    @*INC.map({CompUnitRepo.new($_)})».IO».Str.map({ /\/$/ ?? $_ !! $_ ~ '/' }).list).flat.list;
 }

 sub module-names(Str $modulename) {
-    $modulename.split('::').join('/')
-        X~ '.pm', '.pm6', '.pod';
+    [$modulename.split('::').join('/')
+        X~ <.pm .pm6 .pod>].list;
 }

 sub locate-module(Str $modulename) {
-    my $m = (search-paths() X~ module-names($modulename)).first: *.IO.f;
+    my $m = (search-paths() X~ module-names($modulename).list).first: *.IO.f;
     unless $m.defined {
         my $message = join "\n",
             "Cannot locate $modulename in any of the following paths:",
```

三度目の正直でレッツ・トラ

```bash
$ p6doc Array.push
Cannot locate Array in any of the following paths:
  /usr/local/bin/../doc/perl6/lib/Type/
  /usr/local/bin/../doc/perl6/lib/Language/
  /usr/local/bin/../doc/perl6/lib/Routine/
  /usr/local/bin/../lib/Type/
  /usr/local/bin/../lib/Language/
  /usr/local/bin/../lib/Routine/
  /Users/b73w56h84/.perl6/2015.09/lib/
  /Users/b73w56h84/.perl6/2015.09/
  /usr/local/Cellar/rakudo-star/2015.09/share/perl6/lib/
  /usr/local/Cellar/rakudo-star/2015.09/share/perl6/vendor/lib/
  /usr/local/Cellar/rakudo-star/2015.09/share/perl6/site/lib/
  /usr/local/Cellar/rakudo-star/2015.09/share/perl6/
  /usr/local/Cellar/rakudo-star/2015.09/share/perl6/vendor/
  /usr/local/Cellar/rakudo-star/2015.09/share/perl6/site/
```

あびゃぁー＾q＾

## Arrayクラスが無い？

Arrayはあります。見つけられないだけです。

```bash
$ find /usr/local/Cellar/rakudo-star/2015.09/share/perl6 | grep Array
/usr/local/Cellar/rakudo-star/2015.09/share/perl6/lib/Type/Array.pod
```

これは、前述の`p6doc`の`search-paths()`を修正すれば良いんですかね。
でも、シンボリックリンクで逃げてしまいます。

```bash
$ mkdir -p /usr/local/doc/perl6/lib
$ ln -s /usr/local/Cellar/rakudo-star/2015.09/share/perl6/lib/Type /usr/local/doc/perl6/lib
```

## `p6doc`コマンドでドキュメントを見る

```
$ p6doc Hash.push

  method push

    multi method push(Hash:D: *@new)

Adds the @new elements to the hash with the same semantics as hash assignment,
but with three exceptions:

  * The hash isn't emptied first, i.e. old pairs are not deleted.

  * If a key already exists in the hash, and the corresponding value is an
  Array, the new value is pushed onto the array (instead of replacing it).

  * If a key already exists in the hash, and the corresponding value is not an
  Array, old and new value are both placed into an array in the place of the old
  value.

Example:

    my %h  = a => 1; %h.push: (a => 1);                  # a => [1,1] %h.push:
    (a => 1) xx 3 ;            # a => [1,1,1,1,1] %h.push: (b => 3);
    # a => [1,1,1,1,1], b => 3

Also note that push can be used as a replacement for assignment during hash
initialization very useful ways. Take for instance the case of an inverted
index:

    my %wc = 'hash' => 323, 'pair' => 322, 'pipe' => 323; (my %inv).push:
    %wc.invert.unique; say %inv;                           # 322 => 'pair', 323
    => ['hash','pipe']

Note that such a initialization could also be written as

    my %inv .= push: %wc.invert.unique;
```

やったね(穏やかな目)

おわりです。

# 参考と注釈

[^rakudo]: Perl6コンパイラ
[^yoiko]: 誰か正しい動かし方教えて下さい。~~なんでもしますから~~
[^p6doc-index]: [`p6doc-index build` does not work #137](https://github.com/perl6/doc/issues/137)
[^tot]: バグ報告されたの tokuhirom さんですね。すてき。
[^p6doc]: [command line "p6doc -f push" doesn't work #138](https://github.com/perl6/doc/issues/138)