LoginSignup
2
1

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-09-12
1 / 39

fluorite-7の
生まれた背景


九九表の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

こうか

$ 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

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

say join "\n", map { $a = $_;
  join ",", map { $b = $_;
    $a * $b
  } 1 .. 9
} 1 .. 9
1から9までの各aにおいて、(
 1から9までの各bにおいて、(
  abの積
 )を , で結合したもの
)を改行で結合したものを出す

(短さではなく)


数式(?)

1から9までの各aにおいて、(
 1から9までの各bにおいて、(
  abの積
 )を , で結合したもの
)を改行で結合したものを出す

image.png


jq

こうか

$ 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

長い・打ちにくい

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
九九表を出すぐらい数式程度のインク量でいい


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

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

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


jqはmapが1文字で済む

$ 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する

$ perl -E 'say 1'
1
$ jq -n '1'
1

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


こういうのでいい

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

イメージ

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

こういう言語無いか

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


 pegjs onlineで頑張る

2020-09-11 21_50_24.png

pegjsコード


成れの果て

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

↑理想 現実↓

$ 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

圧倒的短さ

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 * _]'

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


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


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

$ fl7 '1 .. 3'
1
2
3

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

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


「パイプ」

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

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

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


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

$ 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みたいにリスト構造を主軸にしよう


( )は平坦になる

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

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

$ 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なので整数と小数の区別が苦手


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

$ 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扱えるようにしよう

$ 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個の文字列にする

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

$ fl7 '
  a : 11;
  b : 6;
  b = 5;
  a * b
'
55
  • var : defaultValue 宣言
  • var = newValue 代入

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

$ 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)

文字列埋め込みとか

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

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

偽ERB

$ 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>

制御構文

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

$ fl7 '  1 .. 3 | (  OUT(_);  );  '
1
2
3
  • 予約語などというつまらないものはない
  • 定数はある

単位計算的なの

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

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


外部プロセス

$ 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から利用可能なライブラリだ!


怪文書

$ 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

スクリプト言語化

$ echo '{定数 : 77777}' > lib.fl7
$ echo '@USE("lib.fl7"); "定数 is $定数"' > scr.fl7
$ fluorite7 scr.fl7
定数 is 77777
  • USEでライブラリ読み込み
  • 前置@でインポート
  • 非ASCII文字は全部まとめてラテン文字扱い

オンラインエディタ

image.png


影響を受けた言語

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

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


まとめ


まとめ

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

ファイル名ファイル名
↑ロゴ     ↑実在のFluoriteの写真


リンク集

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1