perlsecret


[奥歯にものが挟まった](https://qiita.com/bunzaemon/items/92f97dcee9b23800e797)感じが嫌で、久々に Perl について Web 徘徊してたら、[perlsecret](https://metacpan.org/dist/perlsecret/view/lib/perlsecret.pod) なるページに遭遇。

数々のテクニックに「懐しいなあ」「勝手に名前付けちゃっていいの」なんて思いながら見ていると、`-M5` もあったよ。`Maori farewell` って名前が付いてる。


`-M5` ってのは、

```
% perl -lpe 'BEGIN{ "ARGV"->[0] = "test.txt" }'
```

の代りに、

```
% perl -M'5;"ARGV"->[0]="test.txt"' -lpe1
```

と書く方法。

今日まで忘れてたし、明日からも使わないだろうけど。

<br>
<br>

でだ。



このページ、2024/06/29 現在 [日本語 Wikibooks](https://ja.wikibooks.org/wiki/Perl/%E6%BC%94%E7%AE%97%E5%AD%90#%E7%A7%98%E5%AF%86%E3%81%AE%E6%BC%94%E7%AE%97%E5%AD%90)  に転載されてるんですよ。[^1][^2]

[^1]: 一応、[Web Archieve](https://web.archive.org/web/20231204071145/https://ja.wikibooks.org/wiki/Perl/%E6%BC%94%E7%AE%97%E5%AD%90#%E7%A7%98%E5%AF%86%E3%81%AE%E6%BC%94%E7%AE%97%E5%AD%90)。

[^2]: 途中で諦めたみたいだけど。

あの、、、`perlsecret` のページは、単にこの Philippe Bruhat[^3] って人が収集・主張してるだけだよ？
Philippe Bruhat さんは、おそらく [ここ](https://www.nntp.perl.org/group/perl.fwp/2005/02/msg3691.html)のページとかで触発されたのだろうけど(本人も居る)。

[^3]: フランスの人っぽい。2000年頃から、Perl 関係の専門書のフランス語訳や、フランス版の専門書を書いたりしている人みたい。ただし程度の程は不明。CPAN にモジュールも登録してるけど、どのくらい使われているものか。名前からしたら `HTTP::Proxy` とか使われていそうだけど、生憎不案内で分らない。

Wikibooks の方にコメントしようかとも思ったが、巻き添えアク禁されている。

って事で、ちょっと突っ込みを入れてみる。


<br>

## 命名について

perlsecret のページの下にリファレンスがあるのだけれど、`Baby cart`は、この人がスレッドを立てて募集しただけだし、`Flaming X-Wing` は何のことはない、 [この人が考えて名前を付けてもらっただけ](https://www.nntp.perl.org/group/perl.fwp/2007/11/msg4006.html)。`Venus` に至っては、この人が自分で付けたもの。金星の意味か、女神の意味か。

クリックが面倒だから見てないけど、このノリで付けた名前がどのくらい含まれているのだろうか。

まあ、[ここ](https://www.nntp.perl.org/group/perl.fwp/2005/02/msg3691.html) のページ(2005年)時点で、`eskimo` や、`goatse` など既に使われていたものもある様だが。[^4]

[^4]: 確かに `goatse` は `Perl Best Practices` 辺りの本にも載ってた、、、かな？ 記憶の改竄が起ったか？

<br>

## 機能について

機能については、明らかにコードゴルフ用のものが多い。で、数個程ピックアップ。

### Venus: `0+`

名前を付ける事すら不必要なレベル。文字列を数値化するためのテクニック。Perl の中級者以上の解析系の人なら誰でもお世話になるし、PHP とかでも同様のテクニックがある。

口頭で説明するときに「0 足して」でいいじゃん。「Venusして」とか言うの？ 余計に説明が必要になるだけじゃん。


<br>

### Baby cart: `@{[]}`

`perldoc` とかに記載されているレベルのものに名前を付けるって、どう言う気持だろう。[^5]

[^5]: ちょっと探しただけでも、`perldoc perlref` や `perldoc -f scalar` に記載されてんだよね。

そして、`@{[]}` に名前付けて `%{{}}` が無いとか、、、[^6]

[^6]: この例は `% perl -le 'print Dumper {1,2};' -MData::Dumper` でいい訳だが。まあ、例なので御勘弁を。

```
% perl -le 'print Dumper \%{{qw(1 2)}};' -MData::Dumper
$VAR1 = {
          '1' => 2
        };
```

まあ、コードゴルフでは、`%{{}}` の出番はないのだけれどね。

<br>


### Space station: `-+-`

は、`0+` の結果を `x N` したい時に多少かっこ良く書けます程度。[^7]

[^7]: エラー番号を取得する `print -+- $!, ' ', $!;` も `print 0+ $!, ' ', $!;` すりゃいいだけだし。

他では利用価値はない。
どんだけニッチな用途向けの機能に名前付けてんの？

```
# 普通は
% perl -le 'print + (0+"2a") x 3;'
222
# Space station
% perl -le 'print -+- "2a" x 3;'
222
```

で、 `-` が付く文字列には使えません、ってお粗末さ。

```
% perl -le 'print -+- "-2a" x3;'
-2a-2a-2a
```

数値含まない文字列は文字列のまま、、、しかも `+` が付く。

```
% perl -le ' print -+- "two cents";'
+two cents
```

<br>

<details>
<summary>一応の解説</summary>

をする。`perldoc perlop` からの引用あり。


#### `perl -le 'print + (0+"2a") x 3;`

まずは普通のやり方。(perlsecret のページでは、`print ((0+"2a") x3)` としている。)


```
% perl -le 'print 0+ "2a";'
2
```
の様に、二項演算子の + で文字列を数値化したいが、

```
% perl -le 'print "2a" x3;'
2a2a2a

% perl -le 'print 0+ "2a2a2a"'
2
```
優先順位は `x` > `+` なので `2a2a2a` と言う文字列が作成され `0+` しても 2 しか返さない。

仕方ないので、`()` でくくるが

```
% perl -le 'print (0+"2a") x3;'
2
```

こんどは、リストコンテキストなので、後ろの 2 つの `(0+"2a")` がプリント時に無視される。

```
# 以下と同じ
% perl -le 'print (0+"2a"), (0+"2a"), (0+"2a");'
2
```

仕方ないので、単項演算子の `+` の "関数名に続けて括弧付きの式を書く場合に、関数の引数リストと 解釈されないようにするために用いることができます。" 機能を用いて

```
% perl -le '$, = " " ; print + (0+"2a") x3;'
2 2 2
```

目的のものを出力する。上では、リストコンテキストだと判り易い様に、`$,` を変更している。


```
% perl -le '$a = (0+"2a") x3; print $a'
222
```

変数に代入する(= スカラコンテキストが強制される)場合は、`+` も要らない。

<br>


#### `perl -le 'print -+- "2a" x 3;'`

`Space station` の場合

```
% perl -le 'print - "2a";'
-2
```

で単項演算子の `-` で文字列を数値と見做し算術否定(+ なら - にする)。 [^8]

[^8]: この時点で `-` 付き文字列は、"被演算子の最初の文字がプラスかマイナスのときには、 その記号を逆のものに置き換えた文字列を返します。"に該当するので "-2a" を "+2a" と返し、脱落。

```
% perl -le 'print -- "2a";'
Can't modify constant item in predecrement (--) at -e line 1, at EOF
Execution of -e aborted due to compilation errors.
```

それを更に算術否定したいけど怒られるので、

```
% perl -le 'print -+- "2a";'
2
```

単項演算子の `+` を挟む。[^9]

[^9]: 単項演算子の `+`  はなにもしない。

で、返されたのは文字列なので、

```
% perl -le 'print -+- "2a" x3;'
222
```

二項演算子の `x` で 3倍する。

<br>

#### 蛇足: Inchworm `~~` について


```
% perl -le 'print ~~ (0+"2a") x3;'
222
```

は、スカラー化した `2` を `x3` するので、`print + (0+"2a") x3;` とは似て非なるもの。

また、`-` 付き数値を取り出したい場合は、

```
% perl -le 'print ~~ (0+"-2a") x3;'
184467440737095516141844674407370955161418446744073709551614
```

と言う楽しい事態に陥いるので注意が必要だ。つか、普通に `scalar` 使おう。

```
% perl -le 'print scalar (0+"-2a") x3;'
-2-2-2
```

<br>

</details>

<br>


### Flaming X-Wing: `=<>=~`


```
% perl -le 'my @d = ( <> =~ /^(.*?)$/ ) ; print Dumper \@d;' -MData::Dumper hoge.pl
$VAR1 = [
          '#!/usr/bin/env perl'
        ];
```

の `()` を外しました、ってだけ。

上の方のページ見たら解るけど、「カッコイイだろ、名前付けてよ！」ってノリ。

<br>

### Kite: `~~<>`

[古い記事](https://codehex.hateblo.jp/entry/2017/12/25/184211)に反応するのもアレだけど。

`<>` は、

```
% perl -le 'my @d = <>; print Dumper \@d' -MData::Dumper
1             # <= 手入力

```

ってやると、`<>` はリストコンテキストでの代入だから、無限に入力待ちをする[^10]が、

[^10]: 正確には、`^D` で止めるまで

```
% perl -le 'my $s = <>; print Dumper $s' -MData::Dumper
1             # <= 手入力
$VAR1 = '1
';
```

スカラコンテキストでの代入は、1回の入力で制御が戻る。

で、リストコンテキスト内で、個々にスカラコンテキスト的に挙動させたい場合に、Kite が役立つよ！って話

```
% perl -le 'my @d = (~~<>, ~~<>, ~~<>); print Dumper \@d' -MData::Dumper
1             # <= 手入力
2             # <= 手入力
3             # <= 手入力
$VAR1 = [
          '1
',
          '2
',
          '3
'
        ];
```

ぶっちゃけ、使い所は無い。おそらくコードゴルフでも使うことはない。

<br>


### 総評

もちろん、有用なものもあるけれど、酒のつまみにネタとして楽しむレベルのページ。Philippe Bruhat さんも、参照先のページの方々も、そう言うノリなの見え見えじゃん。コードゴルフの時に、雷電さん役の人[^11]が、解説時に使用するための参考文書が最適な利用方法だったか(過去形)。

[^11]: 知っているのか雷電！ 古い、、、

従って、個人ブログで 「Perl テクニック！」とか銘打って載せる(挙動を解説する)にはいいけど、辞書的なものに載せるには適さないんじゃないかな。

<br>

最後に、perlsecret からの文章を Deep L して引用。

>これらの "演算子 "の多くは、一般的なイディオムの名前にすぎないものもあるが、素人にはわかりにくいため、プロダクション・コードには適さない。本当に秘密の演算子は、ゴルファーや隠蔽者、お気に入りのプログラミング言語で楽しむのが好きな人たちが使うものだ。
>
>自宅で試すのは自由だが、仕事には使えないかもしれない！

<br>
<br>