【Processing 2022】@yuruyurau さんの #つぶやきProcessing のプログラムを短縮されてない #p5js のプログラムにした結果と過程の話

## はじめに
この記事は、[Adventar](https://adventar.org/) で立ち上げられている「[Processing Advent Calendar 2022](https://adventar.org/calendars/7370)」の 1日目の記事です。

この記事の内容は、以下の記事にあるように、過去にも何度か行ったことがある「#つぶやきProcessing のプログラムを、短縮された状態ではないものに書きかえてみる」というものと、その過程を解説するという内容です。

- [#つぶやきProcessing で気になった作品を p5.js Web Editor で動かそうとしてみる【 #GWアドベントカレンダー 2021/5/2 】 - Qiita](https://qiita.com/youtoy/items/0806ba53db59261da3f8)
- [#つぶやきProcessing で気になった作品を p5.js Web Editor で動かしてみる 【その2】 - Qiita](https://qiita.com/youtoy/items/ac2f953d9a0ced3b881a)
- [つぶやきProcessing用に書かれた Processing・p5.js のプログラム（対象2つ）を p5.js で書きかえてみる - Qiita](https://qiita.com/youtoy/items/621379e992ce6403d639)

### 余談
今年、1人で 1つのカレンダーを全部埋めて記事を書いたら、もれなく「完走賞」をいただけるという話があり、以下のような 1人アドベントカレンダーを立ち上げてみたりしています。
※ ちなみに、自分が使っている技術・関わっているコミュニティに関する各種カレンダーにもたくさん登録していて、アドベントカレンダー関連で今年は全40記事以上を書く予定という状況...😂

●完走賞ゲットのため小ネタを毎日投稿しようとチャレンジするのカレンダー | Advent Calendar 2022 - Qiita
　https://qiita.com/advent-calendar/2022/youtoy

こちらのカレンダー 1日目の記事で扱う技術も、本記事で扱っている p5.js となっています(※ 以下の記事)。

[■ 【完走賞ゲット-1】p5.js Web Editor で Google Fonts の絵文字の Webフォントを利用する - Qiita](https://qiita.com/youtoy/items/34920d8a49f45653d77a)

（なお、1人アドベントカレンダーのその後の記事でも、おそらく p5.js関連のものが複数回登場すると思われます）

## 今回の書きかえ対象と書きかえ後の内容
今回、書きかえの対象になるプログラム（p5.js で書かれたもの）は、以下のツイートのものです。
「この短いコードで、なぜこんな不思議な見た目ができるんだ！？」と衝撃を受けた作品でした。

https://twitter.com/yuruyurau/status/1588062547315679232

この内容を読みといてみたいと思い、そのためには短縮されて読み取りづらいと思った内容を、短縮されてない状態にしたいと思いました。
それで書きかえを行い、その結果をツイートしたものが以下となります。

https://twitter.com/youtoy/status/1588808301542006786

この書きかえ後のプログラムを Facebook や　Twitter で投稿・ツイートしていたら、「内容が読み取りやすくなった」というコメントをもらえたり、また「書きかえ途中の過程・やり方を知りたい」というコメントも複数いただきました。
それで、今回の 2022年の Processing のアドベントカレンダーの 1日目の記事で、それができればと思いました。

### プログラムの部分を取り出したもの
上で掲載していたツイート内の p5.js のプログラムの部分を取り出してみます。
以下に、書きかえ前（※ 元のものに、p5.js Web Editor上で整形だけ適用）と書きかえ後の完成版を掲載します。

```javascript:書きかえ前（※ 元のものに、p5.js Web Editor上で整形だけ適用）
$ = [];
draw = (_) => {
  $[0] ?? createCanvas(540, 540);
  background(0, 9);
  $ = $.map(
    (v, i) =>
      stroke(i, i / 3, i / 5).point(v.copy().add(2, 1.6).mult(135)) +
      v.add(
        sin(v.y * (r = ((v.x * 2 + 2.5) ^ (v.y + 2)) * 8)) / 90,
        cos(v.x * r) / 90
      )
  )[2e3]
    ? $.slice(-1980)
    : [...$, ...[...Array(20)].map(p5.Vector.random3D)];
};
```

```javascript:書きかえ後
$ = [];

function setup() {
  createCanvas(540, 540);
}

function draw() {
  background(0, 9);
  const arr = $.map((v, index) => {
    stroke(index, index / 3, index / 5);
    point(v.copy().add(2, 1.6).mult(135));
    const r = ((v.x * 2 + 2.5) ^ (v.y + 2)) * 8;
    return v.add(sin(v.y * r) / 90, cos(v.x * r) / 90);
  });
  if (arr[2000]) {
    $ = $.slice(-1980);
  } else {
    const $2 = [];
    for (let i = 0; i < 20; i++) {
      $2.push(p5.Vector.random3D());
    }
    $ = [...$, ...$2];
  }
}
```

それでは、以下で書きかえの過程について、説明をしていきます。

## 書きかえの過程
### 書きかえ第一弾
今回の書きかえをやっていく際、ちょこちょこ書きかえてみては動作を確認してみる、というのをやっていました。

#### 書きかえ途中のもの
その途中段階の 1つを、以下に掲載してみます。

```javascript:書きかえ途中
$ = [];

function setup() {
  createCanvas(540, 540);
}

function draw() {
  background(0, 9);
  const arr = $.map(
    (v, i) =>
      stroke(i, i / 3, i / 5).point(v.copy().add(2, 1.6).mult(135)) +
      v.add(
        sin(v.y * (r = ((v.x * 2 + 2.5) ^ (v.y + 2)) * 8)) / 90,
        cos(v.x * r) / 90
      )
  );
  if (arr[2000]) {
    $ = $.slice(-1980);
  } else {
    $2 = [...Array(20)].map(p5.Vector.random3D);
    $ = [...$, ...$2];
  }
}
```

まず、この途中段階のものに変わった過程を少し補足します。

#### 最初に行った対応
最初は、 `setup()` を利用しないやり方にされていた部分を、 `setup()` を利用する形にしました。以下の部分の話です。

```javascript:書きかえ前
draw = (_) => {
  $[0] ?? createCanvas(540, 540);
  ...
```

```javascript:書きかえ後
function setup() {
  createCanvas(540, 540);
}

function draw() {
  ...
```

#### 次に行った対応

次は、以下の[三項演算子](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Conditional_Operator)が使われた部分を、三項演算子を使わない形にしてみました。

```javascript:書きかえ前
  $ = $.map(
    ...
  )[2e3]
    ? $.slice(-1980)
    : [...$, ...[...Array(20)].map(p5.Vector.random3D)];
```

以下の形にしました。
その際、「2e3」は「2000」という表記に変更しています。また、最後の 1行を　2行に分割した形に書きかえています。

```javascript:書きかえ前
  const arr = $.map(
    ...
  );

  if (arr[2000]) {
    $ = $.slice(-1980);
  } else {
    $2 = [...Array(20)].map(p5.Vector.random3D);
    $ = [...$, ...$2];
  }
```

### 書きかえ第二弾（最終版の完成）
最終版に向けた書きかえが、あともう少しあります。

#### 行った対応3
次は、個人的な好みで書きかえたという感じもあるのですが、ランダムなベクトルの配列を生成する部分に関するものです。

元は、以下の処理を組み合わせていた形でした。

- [スプレッド構文（「...」を使うやり方）](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)
- [Array.prototype.map()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
- [p5.Vector](https://p5js.org/reference/#/p5.Vector) の [random3D()](https://p5js.org/reference/#/p5.Vector/random3D)

処理的には、要素 20個の空の配列を作成し、そこで mapメソッドを使った配列へのランダムなベクトルの代入を行っているようでした。

```javascript:書きかえ前
$2 = [...Array(20)].map(p5.Vector.random3D);
```

なんとなく個人的には、以下のように書いたほうが自分が読みやすかったので、このようにしてみました（あまり、mapメソッドを多用していないのがあり...）。

```javascript:書きかえ後
    const $2 = [];
    for (let i = 0; i < 20; i++) {
      $2.push(p5.Vector.random3D());
    }
```

#### 行った対応4
これで、書きかえ途中の過程の説明は最後になります。
まず、書きかえ前と後の内容を掲載します。

```javascript:書きかえ前
  const arr = $.map(
    (v, i) =>
      stroke(i, i / 3, i / 5).point(v.copy().add(2, 1.6).mult(135)) +
      v.add(
        sin(v.y * (r = ((v.x * 2 + 2.5) ^ (v.y + 2)) * 8)) / 90,
        cos(v.x * r) / 90
      )
  );
```

```javascript:書きかえ後
  const arr = $.map((v, index) => {
    stroke(index, index / 3, index / 5);
    point(v.copy().add(2, 1.6).mult(135));
    const r = ((v.x * 2 + 2.5) ^ (v.y + 2)) * 8;
    return v.add(sin(v.y * r) / 90, cos(v.x * r) / 90);
  });
```

まず、[アロー関数式](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)の「関数内のコードが式1つだけの場合に、中括弧と return が省略できる」というのが適用されているので、それを中括弧と return を使ったものに書きかえます。

これにより、関数式の中で複数の式を書けるようになりました。

そして、 `stroke().point() + v.add()` という形で複数の式が 1つにまとめられているところをばらしたり（※ 単純に分割するだけで OK）、最後の部分の中に含まれていた `r` を外に出したりしました。
（あと、細かなところで `i` を `index` に変更したりも）

これで、冒頭に掲載していたプログラムに書き換わりました。

## おわりに
これで無事、短縮されたプログラムを、省略されてない形に書きかえることができました。

ちなみに、内容を読みとくというのは、途中までで完了させられておらず...
（これも記事のネタにできそうかな、という思いがありつつ）

## 【追記】 ソースコードを解析した話の記事が出ました
Processing Advent Calendar 2022 の 14日目の記事で、 @clown0082 さんが、ソースコードを解析されて Zenn で記事を書かれていました。

●私が感動した Processing 製の作品のソースコードを解析してみた
　https://zenn.dev/kkeeth/articles/tweet-processing-20221104