創作プログラミング言語　fluorite-7


# fluorite-7の<br>生まれた背景

----

## 九九表のCSVを出したい

こんなの

```
1,2,3,4,5,6,7,8,9
2,4,6,8,10,12,14,16,18
3,6,9,12,15,18,21,24,27
4,8,12,16,20,24,28,32,36
5,10,15,20,25,30,35,40,45
6,12,18,24,30,36,42,48,54
7,14,21,28,35,42,49,56,63
8,16,24,32,40,48,56,64,72
9,18,27,36,45,54,63,72,81
```

----

## perl

こうか

```bash:
$ perl -E 'for $a (1 .. 9) { say join(",", map { $a * $_ } 1 .. 9) }'
1,2,3,4,5,6,7,8,9
2,4,6,8,10,12,14,16,18
3,6,9,12,15,18,21,24,27
4,8,12,16,20,24,28,32,36
5,10,15,20,25,30,35,40,45
6,12,18,24,30,36,42,48,54
7,14,21,28,35,42,49,56,63
8,16,24,32,40,48,56,64,72
9,18,27,36,45,54,63,72,81
```

----

## 可読性もっとよくならないか

```perl:
say join "\n", map { $a = $_;
  join ",", map { $b = $_;
    $a * $b
  } 1 .. 9
} 1 .. 9
```

```perl:
1から9までの各aにおいて、（
　1から9までの各bにおいて、（
　　aとbの積
　）を , で結合したもの
）を改行で結合したものを出す
```

（短さではなく）

----

## 数式(？)

```perl:
1から9までの各aにおいて、（
　1から9までの各bにおいて、（
　　aとbの積
　）を , で結合したもの
）を改行で結合したものを出す
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280627/c818c0b0-b036-df0b-e9f1-de833b9bd6ea.png)

----

## jq

こうか

```bash:
$ jq -nr 'range(1; 10) as $a | [range(1; 10) | $a * .] | @csv'
1,2,3,4,5,6,7,8,9
2,4,6,8,10,12,14,16,18
3,6,9,12,15,18,21,24,27
4,8,12,16,20,24,28,32,36
5,10,15,20,25,30,35,40,45
6,12,18,24,30,36,42,48,54
7,14,21,28,35,42,49,56,63
8,16,24,32,40,48,56,64,72
9,18,27,36,45,54,63,72,81
```

----

## 長い・打ちにくい

```bash:
perl -E 'say join "\n", map { $a = $_; join ",", map { $b = $_; $a * $b} 1 .. 9} 1 .. 9'
jq -nr 'range(1; 10) as $a | [range(1; 10) | $a * .] | @csv'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280627/c818c0b0-b036-df0b-e9f1-de833b9bd6ea.png)
九九表を出すぐらい数式程度のインク量でいい

----

## perlは範囲演算子が2文字で済む

```bash:
$ perl -E 'say        1 .. 9    '
123456789
$ jq -n '         range(1; 10)  '
1
2
3
4
5
6
7
8
9
```

頻出するので演算子でいいんじゃないかな

----

## jqはmapが1文字で済む

```bash:
$ perl -E 'say   map {   $_ * 10   }   1 .. 9    '
102030405060708090
$ jq -n 'range(1; 10)   |   . * 10'
10
20
30
40
50
60
70
80
90
```

頻出するので演算子でいいんじゃないかな

----

## jqは自動的に改行つきでprintする

```bash:
$ perl -E 'say 1'
1
$ jq -n '1'
1
```

値だけポンと置いて勝手に表示してくれた方が楽

----

## こういうのでいい

```
a ∈ 1 .. 9 | [b ∈ 1 .. 9 | a * b]
```

- デフォで改行区切りで自動出力
- `var ∈ list | formula` = `map { $var = $_; formula } @list`
- `[` `]` で囲むと`,`区切りで横に並べる

----

## イメージ

```bash:
$ hoge 'a ∈ 1 .. 9 | [b ∈ 1 .. 9 | a * b]'
```

こういう言語無いか

面白そうだから作ろう（既にあると思うけど知らん）

----

##　pegjs onlineで頑張る

![2020-09-11 21_50_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280627/cbf702ad-9ded-9d09-65f2-3b90ca5833df.png)


[pegjsコード](https://github.com/MirrgieRiana/fluorite-7/commit/0856e62844bc58b3b7320f77b0b96b2dc0942a33#diff-8c6763122a709c84aad4c0b0735b7c33)

----

## 成れの果て

```bash:
$ hoge 'a ∈ 1 .. 9 | [b ∈ 1 .. 9 | a * b]'
```

↑理想　現実↓

```bash:
$ fl7 'a : 1 .. 9 | [1 .. 9 | a * _]'
1,2,3,4,5,6,7,8,9
2,4,6,8,10,12,14,16,18
3,6,9,12,15,18,21,24,27
4,8,12,16,20,24,28,32,36
5,10,15,20,25,30,35,40,45
6,12,18,24,30,36,42,48,54
7,14,21,28,35,42,49,56,63
8,16,24,32,40,48,56,64,72
9,18,27,36,45,54,63,72,81
```

----

## 圧倒的短さ

```bash:
node -e 'console.log(Array.from({length: 9}, (v, k) => k + 1).map(a => 
Array.from({length: 9}, (v, k) => k + 1).map(b => a * b).join(",")).join("\n"))'

perl -E 'say join "\n", map { $a = $_; join ",", map { $b = $_; $a * $b} 1 .. 9} 1 .. 9'

jq -nr 'range(1; 10) as $a | [range(1; 10) | $a * .] | @csv'

fl7 'a : 1 .. 9 | [1 .. 9 | a * _]'
```

極限低文字数アタックでなく、
その言語の標準的な書き方で短いのがポイント

----

# こうしてこの言語は始まった

----

## 「ストリーマ」と「配列」

```bash:
$ fl7 '1 .. 3'
1
2
3

$ fl7 '[1 .. 3]'
1,2,3
```

ストリーマは縦、配列は横

----

## 「パイプ」

```bash:
$ fl7 'a : 1 .. 3 | a * 10'
10
20
30

$ fl7 '1 .. 3 | _ * 10'
10
20
30
```

左辺の各値について右辺を評価した結果を返す
変数名は明示しないと`_`になる

----

## 「ストリーマ」と「配列」と「パイプ」

```bash:
$ fl7 '1 .. 3 | [1 .. 3 | 5]'
5,5,5
5,5,5
5,5,5

$ fl7 'a : 1 .. 3 | [1 .. 3 | a * _]'
1,2,3
2,4,6
3,6,9
```

jqみたいに配列を溶かしたり凍らせたりして操作する

----

# perlやjqみたいにリスト構造を主軸にしよう

----

## `(` `)`は平坦になる

```bash:
$ fl7 '1 .. 3, (4 .. 6), (7), ((8), 9)'
1
2
3
4
5
6
7
8
9
```

----

## 折角だから四則演算とか入れよう

```bash:
$ fl7 '  6 + 3,   6 - 3,   6 * 3,   6 / 3  '
9
3
18
2

$ fl7 '  6 < 5 ? 100 : 10000  '
10000

$ fl7 '  10 / 3,   10 `DIV` 3  '
3.3333333333333335
3
```

JSなので整数と小数の区別が苦手

----

## 折角だから関数作れるようにしよう

```bash:
$ fl7 '  (a -> a * 10)(5)  '
50

$ fl7 '  (a -> a(5))(a -> a * 10)  '
50

$ fl7 '  (f -> n -> f(f)(n))(f -> n -> n == 0 ? 1 : n * f(f)(n - 1))(5)  '
120
```

5! = 120

祝☆チューリング完全

----

## 折角だからjqみたいにJSON扱えるようにしよう

```bash:
$ fl7 '  JSON({a : 5; b : [1 .. 4]})  '
{"a":5,"b":[1,2,3,4]}

$ echo '{"a":5,"b":[1,2,3,4]}' | fl7 '  FROM_JSON(&IN).b  '
1,2,3,4
```

- `IN` = 1行ずつの文字列
- 前置`&` = 1個の文字列にする

----

## 折角だから変数作れるようにしよう

```bash:
$ fl7 '
  a : 11;
  b : 6;
  b = 5;
  a * b
'
55
```

- `var : defaultValue` 宣言
- `var = newValue` 代入

----

## 折角だからクラス作れるようにしよう

```bash:
$ fl7 '
  Obj : {
    new : class, val -> class {
      val;
    };
    get_value : this -> this.val;
  };

  obj : Obj::new("Value!!!");

  obj::get_value()
'
Value!!!
```

- クラスもオブジェクトも`{` `}`で作る
- `parent {` `}`で継承つきオブジェクト
- `obj::method(args)` = `obj.method(obj; args)`

----

## 文字列埋め込みとか

```bash:
$ fl7 '  x : 567; "x = $x"  '
x is 567

$ fl7 '  "pi = $%010.4f(PI)"  '
pi = 00003.1416
```

----

## 偽ERB

```bash:
$ fl7 '  %><ul>
  <%= i : 1 .. 5 | %>
    <li><%= i %></li>
  <% %>
</ul><%  '
<ul>

    <li>1</li>

    <li>2</li>

    <li>3</li>

    <li>4</li>

    <li>5</li>

</ul>
```

----

## 制御構文

```bash:
$ fl7 '  TRUE ? (  OUT("Yes");  ) : (  OUT("No");  );  '
Yes

$ fl7 '  1 .. 3 | (  OUT(_);  );  '
1
2
3
```

- 予約語などというつまらないものはない
- 定数はある

----

## 単位計算的なの

```bash:
$ fl7 '
  UNIT_h : a -> a * 60 * 60;
  UNIT_m : a -> a * 60;
  UNIT_s : a -> a;
  (3h + 36m + 15s) / 1h
'
3.6041666666666665
```

クラスと演算子挙動上書き（演算子オーバーライド）を使えば
複雑な単位を持つ計算も簡潔に記述できる

----

## 外部プロセス

```bash:
$ fl7 'EXEC("perl"; "-e", "print 11 * 7")'
77

$ fl7 'EXEC("perl"; "-e", "print 11 * <STDIN>"; "7")'
77

$ fl7 'EXEC("perl"; "-e", %>print $ENV{v} * <STDIN><%; "7"; {v : "11"})'
77
```

すべての外部プログラムはfl7から利用可能なライブラリだ！

----

## 怪文書

```bash:
$ fl7 '  1 .. 100 => GREP >> \(_ == 2 || !(i : 2 .. *SQRT | _ %% i)) => ARRAY  '
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97

$ fl7 '1~10|Fizz*!(_%3)&Buzz*!(_%5)||_  '
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
```

----

## スクリプト言語化

```bash:
$ echo '{定数 : 77777}' > lib.fl7
$ echo '@USE("lib.fl7"); "定数 is $定数"' > scr.fl7
$ fluorite7 scr.fl7
定数 is 77777
```

- `USE`でライブラリ読み込み
- 前置`@`でインポート
- 非ASCII文字は全部まとめてラテン文字扱い

----

## [オンラインエディタ](https://mirrgieriana.github.io/fluorite-7/editor/?s=%0D%0A1~10%7CFizz*!(_%253)%26Buzz*!(_%255)%7C%7C_%0D%0A)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280627/053e721b-7856-4dda-473c-fb170d44602a.png)

----

## 影響を受けた言語

- C　Java　JavaScript　D
- Perl　Ruby　Raku　Groovy
- jq　bash　Haskell
- hg　Excel

やたら機能があるけど、「どこかで見たことのある演算子」が大半を占める

----

# まとめ

----

## まとめ

- fluorite-7は九九表を短く書ける創作プログラミング言語
- 混沌関数型言語
- 実用性は考えてない

<img width="200px" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280627/d5990628-45c1-655d-d538-eab07e1c10c7.png"><img width="200px" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280627/51d1333e-1b8f-777f-cbba-97abdaed7bb2.png">
↑ロゴ　　　　　↑実在のFluoriteの写真

----

## リンク集

- [fluorite-7　日本語チュートリアル](https://qiita.com/MirrgieRiana/items/a0906c72ebfb46693ab5)
- [オンラインエディタ](https://mirrgieriana.github.io/fluorite-7/editor/?s=%0D%0A1~10%7CFizz*!(_%253)%26Buzz*!(_%255)%7C%7C_%0D%0A)
- カレントディレクトリにダウンロード
  - `curl https://raw.githubusercontent.com/MirrgieRiana/fluorite-7/master/install.bash | bash`