J言語でFizzBuzzを作る

# はじめに
プログラミング言語 **J** を使ってFizzBuzzを作ったので、その解説をします。
J言語はとても面白いので、使ってない人もぜひ読んでみてください。

# J言語とは
変態の使うプログラミング言語です。ひたすら記号の羅列で、まず読めません。負の数を表すのに`_5`のように`-(ハイフン)`ではなく`_(アンダースコア)`を使ったり、コメントを表すのが`NB.`だったりと、クセの強い言語です。
そのかわり、慣れてくると**かなり短く**記述できる、便利な言語です。**配列の処理**に優れていて、総和や総乗を求めたり、配列同士で演算したりすることが簡単にできます。**対話型**で実行でき、手軽さもあります。
**マイナーですが、素晴らしい言語です。みんな使うべきです。**

※ 個人の感想が含まれています。

# 実行環境
J言語は、Windows、MacOS、Android、iOSなど、様々なプラットホームで実行できます。
私は J Android を使用してAndroidで実行しています。

J言語の環境は、iOSでなければ[J言語のホームページ](http://jsoftware.com/)からダウンロードできます。
[インストールのページ](https://code.jsoftware.com/wiki/System/Installation)から最新バージョンのリンクに飛び、そのページの **Download and Install** にあるリンクから、それぞれのプラットホームにあったものをダウンロードし、Jシステムをインストールします。
たとえば、Androidなら[apkファイルをダウンロード](https://code.jsoftware.com/wiki/Guides/JAndroid)してインストールできます。

iOSの場合は、[AppStore](https://apps.apple.com/jp/app/j701/id1255235993)からインストールできます。
ただし、iOS版はアップデートされておらず、バージョンがだいぶ古いので注意です。

# FizzBuzz
J言語でFizzBuzzを作る方法はいろいろありますが、私が作ったFizzBuzzがこちらです。

```j:FizzBuzz.ijs
FizzBuzz=: 'FizzBuzz'&(":@]`(4:{.[)`(4:}.[)`[@.((0:=3:|])++:@(0:=5:|])))&>:&i.
```

J言語はFizzBuzzを1行で書けます。しかし、パッと見ただけでは何を書いてるのか全然わかりませんね。~~私もわかりません。~~

`FizzBuzz 15`のように`FizzBuzz`のうしろに適当な整数をつけて実行すると……

```
   FizzBuzz 15
1       
2       
Fizz    
4       
Buzz    
Fizz    
7       
8       
Fizz    
Buzz    
11      
Fizz    
13      
14      
FizzBuzz
   
```

ちゃんとFizzBuzzが出力されます。

## 解説

### J言語の品詞
FizzBuzzを解説する前に、少しJ言語の説明をします。
J言語では、ほかの言語で演算子やリテラルと呼ばれているものを、**動詞**や**名詞**と呼びます。

名詞は、数値や文字列などを指します。たとえば、`123`や`'Hello'`、`1 1 2 3 5 8 13 21 34 55`(配列)などがあります。

動詞は、関数のように引数を受けて計算するものです。足し算や掛け算などをする記号や文字を指します。
動詞に引数を渡す方法は2つで、`(動詞) y`のように右から1つ渡す方法と、`x (動詞) y`のように左右から2つ渡す方法があります。

ほかにも**接続詞**というものがあります。これは動詞や名詞をつなげて、新たな動詞を作るものです。たとえば、2倍する動詞`+:`と2乗する動詞`*:`を接続詞`@`でつなげて、2乗してから2倍する動詞を作ることができます。

```j
   NB. 6番目の電子殻(P殻)に収用できる電子数
   (+: @ *:) 6
72
   
```

**副詞**というものもあります。これは日本語と同じで、動詞を修飾するものです。たとえば、足し算をする動詞`+`に、副詞`/`をつけることで、総和を求める動詞`+/`を作ることができます。

```j
   NB. 114 + 514 + 191 + _9
   +/ 114 514 191 _9
810
   
```

### 動詞を作る
J言語では、自分で動詞を作ることができます。ほかの言語でいうところの、関数を作るようなことです。
FizzBuzzでは、様々な動詞や名詞、副詞を組み合わせて、`FizzBuzz`という一つの動詞を作っています。

### フォーク
**`((動詞a) (動詞b) (動詞c))`**
このように、動詞3つを接続詞なしでつなげて動詞を作ることを**フォーク**といいます。
`(フォーク) y`というふうに引数を1つ渡した場合は
`((動詞a) y) (動詞b) ((動詞c) y)`と評価され、動詞aと動詞cがそれぞれ引数を受け取って計算し、計算されたそれぞれの値を動詞bが受け取って計算します。
`x (フォーク) y`と引数を2つ渡した場合も
`(x (動詞a) y) (動詞b) (x (動詞c) y)`と評価され、同じように計算されます。

```j
   NB. 並列の合成抵抗
   20 (* % +) 5    NB. 積÷和(%は割り算の動詞)
4
   
```

### 右から処理する
J言語では**右から**順番に処理します。そのほうがなにかと都合がいいんです。
たとえば、`3*3-4`は`3-4`が先に計算されるので`_3`になります。

### 解説
では、FizzBuzzを右から順番に見ていきます。

```j
FizzBuzz =: 'FizzBuzz' & ( ": @ ] ` ( 4: {. [ ) ` ( 4: }. [ ) ` [ @. ( ( 0: = 3: | ] ) + +: @ ( 0: = 5: | ] ) ) ) & >: & i.
```

**`i.`**
0 から (引数)-1 までの整数配列を作る動詞です。

**`&`**
動詞と動詞、動詞と名詞を繋げる接続詞です。

**`>:`**
インクリメントする動詞です。`i.`によって作られた`0 1 2 ……`のような配列を、`1 2 3 ……`のように、それぞれの要素をインクリメントします。

**`&`**
接続詞です。

**``(":@]`(4:{.[)`(4:}.[)`[@.((0:=3:|])++:@(0:=5:|])))``**
FizzBuzzしてる部分です。あとで解説します。

**`&`**
接続詞です。

**`'FizzBuzz'`**
文字列です。FizzBuzzしてる部分の左側の引数になります。

**`=:`**
動詞や名詞に名前をつける連結詞です。変数や関数を定義するようなものです。副詞や接続詞などにも名前をつけることができます。

**`FizzBuzz`**
`=:`の右側の動詞の名前です。

つまり、1 から 引数として与えられる整数 までの整数配列と文字列`'FizzBuzz'`を、FizzBuzzしてる部分の引数として渡す動詞を、`FizzBuzz`という名前で定義しているということです。

#### FizzBuzzしてる部分
FizzBuzzしてる部分の解説をします。

```j
( ":@] ` (4:{.[) ` (4:}.[) ` [ @. ((0:=3:|])++:@(0:=5:|])) )
```

**``(動詞0) ` (動詞1) ` …… @. (条件)``**
接続詞の`` ` ``は、*動詞どうし*をつなげて動詞の配列を作ります。
また接続詞`@.`は、左側の動詞の配列から、右側に与えられるインデックスの位置の動詞を返します。

つまりこの構文は、**条件の部分が 0 なら動詞0を、1 なら動詞1を、……** というふうに実行します。

FizzBuzzしてる部分では、`":@]`が動詞0、`(4:{.[)`が動詞1、`(4:}.[)`が動詞2、`[`が動詞3、`((0:=3:|])++:@(0:=5:|]))`が条件にあたります。

---

**条件: `((0:=3:|])++:@(0:=5:|]))`**

条件の部分には[フォーク](#フォーク)が使われています。
フォークしている動詞は、`(0:=3:|])`と`+`と`+:@(0:=5:|])`の3つです。

`(0:=3:|])`を動詞a、`+`を動詞b、`+:@(0:=5:|])`を動詞cとして解説します。

---

**条件: 動詞a: `(0:=3:|])`**

ここにも[フォーク](#フォーク)が使われています。
`0:`と`=`と`3:|]`がフォークになっていて、さらに`3:|]`のなかで`3:`と`|`と`]`がフォークになっています。

**`]`**
右の引数をそのまま返す動詞です。FizzBuzzしてる部分の右の引数は`i.`などを使って作った`1 2 3 ……`のような整数配列なので、それが返ります。

**`|`**
右の引数を左の引数で割った余りを計算する動詞です。

**`3:`**
3 を返す動詞です。引数になにを渡されても、絶対に 3 しか返しません。

**`=`**
右の引数と左の引数が等しければ 1 を、そうでなければ 0 を返す動詞です。

**`0:`**
0 を返す動詞です。引数になにを渡されても、絶対に 0 しか返しません。

動詞aの計算結果は、引数を3で割った余りが0なら 1、そうでなければ 0 になります。
つまり、**3の倍数なら 1、そうでなければ 0** になります。

---

**条件: 動詞c: `+:@(0:=5:|])`**

**`(0:=5:|])`**
ここはさっきとほとんど同じです。5の倍数なら 1、そうでなければ 0 になります。

**`@`**
*動詞どうし*をつなげる接続詞です。

**`+:`**
引数を2倍する動詞です。

つまり動詞cの計算結果は、**5の倍数なら 2、そうでなければ 0** になります。

---

**条件: 動詞b: `+`**

動詞aと動詞cの結果を足します。
つまり条件の部分は、3の倍数かつ5の倍数なら 3、5の倍数なら 2、3の倍数なら 1、それ以外なら 0 になります。

したがってFizzBuzzしてる部分では、整数配列の要素が**3の倍数かつ5の倍数なら動詞3を、5の倍数なら動詞2を、3の倍数なら動詞1を、それ以外なら動詞0を**実行します。

---

**動詞0: `":@]`**

**`]`**
右の引数をそのまま返す動詞です。つまり整数配列です。

**`@`**
接続詞です。

**`":`**
数値を文字列を変換する動詞です。`'Fizz'`や`'Buzz'`は文字列なので、`1`や`4`などの数値も文字列に変えなければうまくいきません。

つまり動詞0は、引数の数値を文字列に変換します。

---

**動詞1: `(4:{.[)`**

ここにも[フォーク](#フォーク)が使われています。

**`[`**
左の引数をそのまま返す動詞です。FizzBuzzしてる部分の左の引数は文字列`'FizzBuzz'`なので、それが返ります。

**`{.`**
配列の要素を取り出す動詞です。配列の要素を指定された数だけ前から取り出して、新たな配列を作ります。

**`4:`**
4 を返す動詞です。

動詞1は、`'FizzBuzz'`の前から4つを取り出します。
つまり、`'Fizz'`を返します。

---

**動詞2: `(4:}.[)`**

ここにも[フォーク](#フォーク)が使われています。
J言語は、フォークのおかげで短く書けるといっても過言ではありません。

**`[`**
左の引数をそのまま返す動詞です。つまり`'FizzBuzz'`です。

**`}.`**
配列の要素を落とす動詞です。配列の要素を指定された数だけ前から落として、新たな配列を作ります。

**`4:`**
4 を返す動詞です。

動詞2は、`'FizzBuzz'`の前から4つを落とします。
つまり、`'Buzz'`を返します。

---

**動詞3: `[`**

動詞3は、左の引数を返します。
つまり`'FizzBuzz'`をそのまま返します。

したがってFizzBuzzしてる部分は、整数配列の要素が**3の倍数かつ5の倍数なら`'FizzBuzz'`を、5の倍数なら`'Buzz'`を、3の倍数なら`'Fizz'`を、それ以外なら文字列に変換した数値を**返します。

---

**これでようやくFizzBuzzができました！**

あとは整数を指定すれば、1からその整数までの配列が作られて、その要素がFizzBuzzに変換されていきます。

## 追記(2020/12/27)

フォークの左の部分には名詞を使うこともできます。
なので、`3:`や`5:`は、`3`や`5`というふうに、単に数値に置き換えることができます。

```j
FizzBuzz=: 'FizzBuzz'&(":@]`(4{.[)`(4}.[)`[@.((0=3|])++:@(0=5|])))&>:&i.
```

# ちなみに
J言語はif文やfor文も使えます。

```j:FizzBuzz.ijs
FizzBuzz =: 3 : 0
for_i. >: i. y do.
  if. 0 = 15 | i do.
    echo 'FizzBuzz'
  elseif. 0 = 3 | i do.
    echo 'Fizz'
  elseif. 0 = 5 | i do.
    echo 'Buzz'
  else.
    echo i
  end.
end.
)
```

~~こっちのほうが読みやすい。~~

# おわりに
最後まで読んでくださって、ありがとうございます。パズルみたいで楽しくなかったですか？
この記事を読んで、J言語に少しでも興味を持ってもらえたらうれしいです。

# 参考サイト
[Jsoftware](http://www.jsoftware.com/)
[J Software - J 言語](https://www.manabusumioka.com/j/)
[J言語基礎講座](http://masa.vis.ne.jp/Jkiso/)
[Rubyist のための他言語探訪 【第 12 回】 APL と J](https://magazine.rubyist.net/articles/0019/0019-Legwork.html)
[J言語の使用によるASCII文字の地獄への手引き - TopCoderとJ言語と時々F#](https://japlj.hatenadiary.org/entry/20100331/1270036168)
[J言語 カテゴリーの記事一覧 - (保存用) 檜山正幸のキマイラ飼育記 メモ編](https://m-hiyama-memo.hatenablog.jp/archive/category/J%E8%A8%80%E8%AA%9E)
[J言語でFizzBuzz - ふるつき](https://furutsuki.hatenablog.com/entry/2019/08/14/103738)
[J言語のエッセンスとクイックレファレンス　そして講義、特にファイル処理（須田）（未定稿）](http://japla.sakura.ne.jp/workshop/workshop/2009/jqref-incomplete-suda-2009-05-17_html.html)