スクリプト言語を作りたい
名前: RocSho
緑青
Rustっぽさ
シェルスクリプトは文法が狂っている
Python, Ruby, Perlは静的型検査がない
なくはない
静的型検査のある、正気の文法をもつ、スクリプト言語
実行時エラーを減らしたい
静的型付け言語
バチバチな型推論
関数型
自動カリー化
再帰は明示的に
Rustスタイルのシャドーイングがしたいので
パイプ演算子
関数barについてfoo.barできるやつあってもよい
関数合成
既定でイミュータブル
トレイト
Rustのと同じ感じ
ある型が実装していてほしいメソッドを定義する
HaskellのNumとかFloatingみたいな抽象化もほしい
参照とコピーを区別したい
既存の言語が雑にやってきた部分
所有権チェッカーを作りたくない
ムーブの概念を消して変数への束縛は基本全てコピーにするみたいな?
Rustでいうと全部の型がClone
メモリ解放はどうやるんだ
Rustは重いのでML系の感じで
括弧でもいい
オブジェクト指向
JavaScriptのようにさくりと書けるレコード機能がほしい
シングルトンでは
プロパティアクセスを関数にしたい
レコードの型推論
JavaScript的に手軽に書けてjqみたいなフィルタで扱えてしかも型がつく let f r = r.foo に {foo: a} -> a みたいな型がついてほしい
文字列はUTF-8
依存関係をまともに扱いたい
WASMパッケージマネージャーがどうなるか?
型
ユーザ定義型名は大文字から始める。組み込み型名もそうしたい。
Bool は真偽値。True と False だけ。条件分岐とかで使う。
整数は 37 のようなリテラルで Int 型。スクリプト用途なんだからビット数なんてどうでもいいだろう。
浮動小数点数型も整数と同様に Float を使う感じで、IEEE754。
数値型に共通の型クラスとして Num を用意して、+ のような演算子は Num インスタンスに適用する関数にしたい。OCaml のような +. とかは見たくない。
文字列型 String は鋼の意志を持ってUTF-8にする。Rustでは実体は Vec<u8> になっているし、そのように持ったほうがいいのか。そもそもWASM側の仕様でそうなる感じがする。文字列リテラルは "" が無難だが、\`A "black" dog\` のようにバッククオートを使う文法にしてもいいかもしれない。どちらにせよ ##"#"fiii"#"## のようなエスケープをできるようにする。
TypeScriptみたいなリテラル型がほしい。そうするとユニオンが必要になり、関数のunionとかが出てきて頭が崩壊する。関数のunionが出てくると必然的にintersectionが出てきて終わりになる。
変数定義
変数宣言は let を使って行う。
code:変数宣言
let h = 42
h + 58
F#と同じ。
let式は一行で書ける。
code:一行
let h = 42 in h + 58
可変変数let mutを作るか迷う。RustとF#にはあってOCamlにはない。
型注釈は後置する。
code:型注釈
let h: String = "foo";
Rustと同じ。
ただし
code:型注釈
val h: String
let h = "foo"
のような文法も許容するかもしれない。
レコード
JavaScriptでいうオブジェクト。レコードへのアクセスを関数にしたいという欲がある。
code:record
// JS-style
let record = { age: 12 }; // record: { age: Int }
println record.age; // ドット
// SATySFi-like
let record = (| age: 12 |); // SATySFiっぽいタイプも検討
println record#age // .を#に置き換えただけ
println (#age record) // #foo が関数になるタイプ match
$ \texttt{match} \space expr \space \texttt{with} \space expr
関数
関数呼び出しはかっこ不要。
code:fn
print "hi"
関数定義もletを使って行う。
code:関数
let f x = x + 1
F#と同じ。Rustは冗長で部分適用の扱いが面倒。
再帰的定義には rec をつける。
code:関数
let rec fact n =
if n == 0
1
else
n * fact(n - 1);
F#と同じ。このようにしないと let a = a + 3 のようなシャドーイングを意図したコードが(無限)再帰になってしまう。
名前付き引数はなし。レコードを使う。
code:引数にレコード
val f: (| a: Int, b: String |) -> Unit
f (|
a: 32,
b: "hogehoge",
|)
直和型
1個以上のバリアントから1つ選ぶ型。ADT。
code:adt
data Bool = True | False
data Option a = Some a | None
レコード
code:record
type Square = {
size : Int
}
トレイト
型クラス相当。
code:typeclass
trait Area
val area : Self -> Float
impl Square for Area
let area { size } =
size * size
let area_sum a b =
area a + area b
Algebraic Effects
code:ae
effect log : Int -> Unit
with handler
| log a -> println(a)
log 1