AiScript Docs
Getting started
Introduction
AiScript(あいすくりぷと)は、プログラミング言語です。 このドキュメントでは、既にある程度のプログラミングの知識があることを前提にしています。 したがってAiScriptの構文、仕様などについてだけ書き、プログラミング自体についての説明は省きます。
参考:syntax.md
Hello, world!
AiScriptでは、次のように書きます:
print("Hello, world!")
print( ~ )
は関数呼び出しです。カッコの前に呼び出す関数名を書き、カッコの中に引数を書きます。
引数が複数あるときは,
で区切って列挙します。
関数についての詳細は後述します。
"~"
は文字列リテラルです。"
で囲ったものが文字列になります。
ちなみに、print( ~ )
には糖衣構文があり、次のようにも書けます:
<: "Hello, world!"
コメント
AiScriptのコメントは//
で始めます。
コメントはプログラムの動作に影響を与えません。
// this is a comment
複数行にわたってコメントアウトする場合、/*
*/
で囲みます。
/*
this is a comment
*/
組み込み型
名称 | 型名 | リテラル例 |
---|---|---|
文字列 | str | "kawaii" |
数値 | num | 42 |
真理値 | bool | true /false |
配列 | arr | ["ai" "chan" "cute"] |
オブジェクト | obj | { foo: "bar"; a: 42; } |
null | null | null |
関数 | fn | @(x) { x } |
エラー | error | (TODO) |
変数
宣言
変数宣言は次のように書きます:
let message = "Hello"
let
のあとに変数名を書き、=
の後に値を書きます。
AiScriptではこの方法で宣言した変数はイミュータブルです。つまり、変数の値を後から変えることは出来ません。
再代入可能な変数を作る時は、let
の代わりにvar
で変数宣言します。例:
// ミュータブルな変数を宣言
var message = "Hello"
// 再代入
message = "Hi"
// また再代入
message = "Yo"
なお、同一スコープ内での変数の再宣言は禁止されています。
参照
変数の値を参照する時は、単に変数名を書きます:
print(message)
配列
[]
の中に式をスペースで区切って列挙します。
["ai", "chan", "kawaii"]
配列の要素にアクセスするときは、[<index>]
と書きます。
インデックスは0始まりです。
let arr = ["ai", "chan", "kawaii"]
<: arr[0] // "ai"
<: arr[2] // "kawaii"
オブジェクト
AiScriptにおけるオブジェクトは文字列のみをキーとした連想配列のようなものとなっています。
キーと値から構成される各要素をプロパティと呼びます。
この時キーをプロパティ名と呼びます。
{}
の中にプロパティを,
/;
/空白で区切って列挙します。
プロパティ名と値は:
で区切ります。
{
foo: "bar"
answer: 42
nested: {
some: "thing"
}
}
オブジェクトのプロパティにアクセスするときは、
.<name>
か[<str>]
と書きます。
let obj = {foo: "bar", answer: 42}
<: obj.foo // "bar"
<: obj["answer"] // 42
演算
演算は、
(1 + 1)
のように書きます。これは標準関数(後述)呼び出しの糖衣構文で、実際にはこのように解釈されます:
Core:add(1, 1)
詳しくは→syntax.md
ブロック式
ブロック式 eval { ~ }
を使うと、ブロック内で最後に書かれた式が値として返されます。
let foo = eval {
let a = 1
let b = 2
(a + b)
}
<: foo // 3
条件分岐
AiScriptでの条件分岐は、次のように書きます:
if (a == b) {
<: "a equals to b"
}
if
の後にboolを返す式(条件)を書き、その後に条件に一致した場合に評価される式(then節)を書きます。
then節の後にelse
を書き、さらに式を追加することで条件に一致しなかった場合の処理も行うことが出来ます:
if (a == b) {
<: "a equals to b"
} else {
<: "a does not equal to b"
}
elif
の後に条件式を書くことで条件判定を複数行うことも出来ます:
if (a == b) {
<: "a equals to b"
} elif (a > b) {
<: "a is greater than b"
} else {
<: "a is less than b"
}
これらの条件分岐は式なので、ブロック内で値を返せます:
<: if (a == b) {
"a equals to b"
} elif (a > b) {
"a is greater than b"
} else {
"a is less than b"
}
繰り返し
AiScriptでの繰り返しは、次のように書きます:
for (let i, 100) {
<: i
}
for
の後にイテレータ変数名を書き、,
の後に繰り返し回数を返す式を書きます。その後のブロックで繰り返す処理を書きます。
イテレータ変数は省略することも出来ます:
for (100) {
<: "yo"
}
繰り返し(配列)
each
を使うと、配列の各アイテムに対し処理を繰り返すことができます:
let items = ["a", "b", "c"]
each (let item, items) {
<: item
}
関数
関数定義
次のように書きます:
@fn(x) {
(x * 2)
}
@
の後に関数名を書き、カッコの中に引数定義を書きます。その後にブロックが関数の処理になります。
return
関数の最後に書かれた式の値が関数の返り値になりますが、関数の途中で値を返したい時はreturn
を使います。
標準定数、標準関数
何も書かなくても最初から使える定数・関数です。
組み込みプロパティ
オブジェクト以外の値に.
をつけて呼び出すことができる擬似的なプロパティです。
テンプレート
バッククォートを使うと、文字列の中に変数や式を埋め込めます:
let ai = "kawaii"
<: `Hello, {ai} world!`
// 結果: Hello, kawaii world!
メタデータ
AiScriptファイルにメタデータを埋め込める機能です。
### {
name: "example"
version: 42
keywords: ["foo", "bar", "baz"]
}
エラー型
一部の標準関数は実行失敗時にエラー型の値を返します。
これによりエラー処理を行うことができます。
@validate(str){
let v=Json:parse(str)
if (Core:type(v)=='error') print(v.name)
else print('successful')
}
エラーメッセージ
進行不能なエラーが発生するとエラーメッセージが表示されます。
let scores=[10, 8, 5, 5]
let 3rd=scores[2] // unexpected token: NumberLiteral (Line 2, Column 5)
let arr=[]
arr[0] // Runtime: Index out of range. Index: 0 max: -1 (Line 2, Column 4)
行(Line)、列(Column)は1始まりです。
実行方法
1. Playgroundから実行
自分でホストする場合は、以下のコマンドを実行し表示されたリンクをブラウザで開きます。
cd playground
npm run build
npm run serve
PlaygroundはGitHubでもホストされています:
https://aiscript-dev.github.io/aiscript/
2. スクリプトファイルから実行
ファイルの内容を解析して実行します。
プロジェクトルートにmain.ais
を作成し、以下の内容を記述しファイルに保存します。
<: "Hello world!"
以下のコマンドを実行します。
$ npm run start
3. スクリプトファイルを解析する (パーサーのデバッグ向け)
ファイルの内容を解析してASTを表示することができます。 主にパーサーのデバッグ向けで、インタプリタの実装状況に関わらずASTの内容を表示することができます。
プロジェクトルートにmain.ais
を作成し、以下の内容を記述しファイルに保存します。
<: "Hello world!"
以下のコマンドを実行します。
$ npm run parse
4. REPL上で実行
コマンドライン上で対話的にコードを実行します。 以下のコマンドを実行し、コードを入力します。
$npm run repl
Syntax
文と式
AiScriptにおける構文要素は、コメント等を除き「文(statement)」と「式(expression)」の2つからなります。
文は行頭または式を受け取る構文要素(ifや関数リテラルなど)にのみ記述することができます。返り値が利用されることを想定されていない構文要素であり、返り値は常にnullです。
対して式は、文を書ける場所に加えて何らかの値を要求するほとんど全ての構文要素の内部に書くことができます。また、多くの場合何らかの意味ある値を返します。
コメント
//
で始めた行や/*
*/
で囲んだ箇所はコメントになり、プログラムの動作に影響を与えません。
// 単行コメント
/*
複数行コメント
*/
バージョン表記
プログラムの一行目に以下の記法を行うことで、想定されたAiScriptのバージョンを明記することができます。
このバージョンはホストプログラムによって読み込まれる場合があります。
/// @ 0.16.0
文
変数・関数宣言
イミュータブル変数(定数)にはlet
、ミュータブル変数にはvar
、関数には@
を使用します。
予約語について
変数や関数の宣言において、名前として使用できないキーワードがいくつかあります。
詳しくはkeywords.mdを参照ください。
変数
// イミュータブル(再代入不可)
let answer = 42
// ミュータブル(再代入可能)
var answer2 = 57
// 初期値の省略は不可
var answer // Syntax Error
// match等の予約語は変数名として使用できない
let match = 12 // Syntax Error
// 同名の変数の再宣言は禁止
var a = 1
var a = 2 // Runtime Error
let a = 3 // Runtime Error
関数
関数宣言はイミュータブル変数を関数で初期化するのと同じ動作になっています。
// 最後の式が暗黙にreturnされる
@add(x, y) {
x + y
}
<: add(1, 2) // 3
// 定数をリテラル関数で初期化しても同じ働きになる
let add2 = @(x, y) {
x + y
}
// 明示的にreturnを書くこともできる
@add3(x, y) {
return x + y
}
// 引数を複数行で書いてもよい
@add4(
x,
y
) {
x + y
}
// 省略可能引数
@func1(a, b?) {
<: a
<: b // 省略されるとnullになる
}
func1('hoge') // 'hoge' null
// 初期値を設定された引数(省略可能引数と組み合わせて使用可能)
@func2(a, b?, c = 'piyo', d?) {
<: a
<: b
<: c
<: d
}
func2('hoge', 'fuga') // 'hoge' 'fuga' 'piyo' null
// 初期値には変数を使用可能(値は宣言時点で固定)
var v = 'hoge'
@func3(a = v) {
<: a
}
v = 'fuga'
func3() // 'hoge'
// ワンライナー
@func4(a,b?,c=1){<:a;<:b;<:c}
// match等の予約語は関数名として使用できない
@match(x, y) { // Syntax Error
x == y
}
// 最後の引数の後にはコロンを付けられない
@add(x, y,) { // Syntax Error
x + y
}
// 変数同様再宣言は不可
var func = null
@func() { // Runtime Error
'hoge'
}
// 省略可能引数構文と初期値構文は併用できない
@func(a? = 1) {} // Syntax Error
代入
宣言済みの変数の値を変更します。
var a = 0
a = 1
<: a // 1
// letで宣言された変数は代入不可
let a = 0
a = 1 // Runtime Error
分割代入
// 配列の分割代入
var a = ''
var b = ''
[a, b] = ['hoge', 'fuga']
<: a // 'hoge'
<: b // 'fuga'
// オブジェクトの分割代入
{ name: a, nature: b } = { name: 'Ai-chan', nature: 'kawaii' }
<: a // 'Ai-chan'
<: b // 'kawaii'
// 組み合わせ
let ai_kun = {
name: 'Ai-kun',
nature: ['kakkoii', 'kawaii', 'ponkotsu'],
}
{ name: a, nature: [b] } = ai_kun
<: a // 'Ai-kun'
<: b // 'kakkoii'
// 宣言で分割代入を使うことも可能
let [hoge, fuga] = ['hoge', 'fuga']
each let { value: a }, [{ value: 1 }, { value: 2 }] {
<: a // 1, 2
}
// 引数でも使用可能
@func([a, b] = [0, 0]) {
[a, b]
}
func([1, 2]) // [1, 2]
func([1]) // [1, null], not [1, 0]
func() // [0, 0]
// 再宣言を含む宣言は不可
var a = 0
let [a, b] = [1, 'piyo'] // Runtime Error
// 名前空間での宣言では使用不可
:: Ai {
// Runtime Error
let [chan, kun] = ['kawaii', 'kakkoii']
}
// 代入値が分割できる型でなければエラー
[a, b] = 1 // Runtime Error
{ zero: a, one: b } = ['hoge', 'fuga'] // Runtime Error
for
与えられた回数のループを行います。
let repeat = 5
for repeat print('Wan') // WanWanWanWanWan
// {}を使うことで複数の文を書ける
for 2 + 3 {
<: 'Nyan'
} // NyanNyanNyanNyanNyan
// ()でくくってもよい
for ({ a: 3 }.a) {
<: 'Piyo'
} // PiyoPiyoPiyo
// {の直前に空白必須
for 5{ // Syntax Error
<: 'Mogu'
}
for-let
イテレータ変数を宣言し、ループ内で参照することができます。
for let i, 5 {
<: i
} // 0 1 2 3 4
// 初期値を設定することもできる
for let i = 3, 5 {
<: i
} // 3 4 5 6 7
// イテレータ変数はletで宣言される必要がある
for var i, 5 {
<: i
} // Syntax Error
each
配列の各要素に対しループを行います。
let arr = ['foo', 'bar', 'baz']
each let v, arr {
<: v
} // foo bar baz
// {の直前に空白必須
each let v, arr{ // Syntax Error
<: v
}
while
条件がtrueの間ループを続けます。
条件が最初からfalseの場合はループは実行されません。
var count = 0
while count < 42 {
count += 1
}
<: count // 42
// 条件が最初からfalseの場合
while false {
<: 'hoge'
} // no output
do-while
条件がtrueの間ループを続けます。
条件が最初からfalseであってもループは一度実行されます。
var count = 0
do {
count += 1
} while count < 42
<: count // 42
// 条件が最初からfalseの場合
do {
<: 'hoge'
} while false // hoge
loop
break
されるまで無制限にループを行います。
var i = 5
loop {
<: i
i -= 1
if i == 0 break
} // 5 4 3 2 1
グローバル専用文
他の構文要素の内部に書くことを許容されない特殊な文です。
これらの構文要素は実行開始時に巻き上げられるため、プログラム上のどこに書いても最初に読み込まれます。
メタデータ構文
オブジェクトリテラルと類似した記法でAiScriptファイルにメタデータを埋め込める機能です。
メタデータはホストプログラムによって読まれる場合があります。
要素として関数を除く純粋なリテラルのみが許可されており、それ以外の式を含むと構文エラーとなります。
### {
name: "example"
version: 42
keywords: ["foo", "bar", "baz"]
}
名前空間
複数の定数・関数に共通した接頭辞をつけることのできる機能です。
ミュータブルな変数の存在は許容されていません。
未発達な機能であり、今後役割が大きく変更される可能性があります。
:: Ai {
let chan = 'kawaii'
@kun() {
<: chan
}
}
<: Ai:chan // kawaii
Ai:kun() // kawaii
式
リテラル
値をスクリプト中に直接書き込むことができる構文です。
詳しくは→literals.md
演算子
主要な演算を表現します。
単項演算子
式に前置して使用します。論理否定(!
)、正数符号(+
)、負数符号(-
)の三種があります。
二項演算子
2つの式の間に置いて使用します。四則演算とその派生(+
,-
,*
,^
,/
,%
)、比較演算(==
,!=
,<
,<=
,>
,>=
)、論理演算(&&
,||
)があります。
演算子の優先度
例えば1 + 2 * 3
などは2 * 3
が先に計算されてから1 +
が行われます。これは*
の優先度が+
より高いことによるものです。優先度の一覧は下の表をご覧下さい。
この優先度は(1 + 2) * 3
のように(
)
で括ることで変えることができます。
二項演算子の糖衣構文性
二項演算子は構文解析の過程でそれぞれ対応する組み込み関数に置き換えられます。
(単項演算子である!
にも対応する関数Core:not
が存在しますが、置き換えは行われていません)
何の関数に置き換えられるかは下の表をご覧下さい。
演算子一覧
上から順に優先度が高くなっています。(一部優先度が同じものもあります)
演算子 | 対応する関数 | 意味 |
---|---|---|
^ | Core:pow | 冪算 |
+(単項) | なし | 正数 |
-(単項) | なし | 負数 |
!(単項) | なし | 否定 |
* | Core:mul | 乗算 |
/ | Core:div | 除算 |
% | Core:mod | 剰余 |
+ | Core:add | 加算 |
- | Core:sub | 減算 |
> | Core:gt | 大きい |
>= | Core:gteq | 以上 |
< | Core:lt | 小さい |
<= | Core:lteq | 以下 |
== | Core:eq | 等しい |
!= | Core:neq | 等しくない |
&& | Core:and | かつ |
|| | Core:or | または |
if
キーワードif
に続く式がtrueに評価されるかfalseに評価されるかで条件分岐を行います。
式として扱うことができ、最後の文の値を返します。
if
の直後に1つ以上の空白またはタブを挟む必要があります。(改行があっても)
条件式がbool
型ではない値に評価されるとエラーになります。
// 単行
if answer == 42 print("correct answer")
// 複数行
if answer == 42 {
<: "correct answer"
}
// 条件式は()で囲ってもよい
if ({ a: true }.a) print('ok')
// 式として使用可能
<: `{if answer == 42 "collect answer"}`
// else, elifも使用可能
let result = if answer == "bebeyo" {
"correct answer"
} elif answer == "ai" {
"kawaii"
} else {
"wrong answer"
}
// elseがない場合、条件式がfalseならnullを返す
<: if false 1 // null
// 条件式の前後の空白は必須(かっこでくくっていても)
if(true) return 1 // Syntax Error
if (true)return 1 // Syntax Error
// elif, elseの直前の空白は必須
if (false) {
}elif (true) { // Syntax Error
}else {} // Syntax Error
eval
別名ブロック式。
{ }
内の文を順次評価し、最後の文の値を返します。
let foo = eval {
let x = 1
let y = 2
x + y
}
<: foo // 3
match
let x = 1
let y = match x {
case 1 => "yes"
case 0 => "no"
default => "other"
}
<: y // "yes"
// ワンライナー
<:match x{case 1=>"yes",case 0=>"no",default=>"other"} // "yes"
exists
与えられた名称の変数または関数が存在すればtrue、しなければfalseを返します。
// 変数barは存在しないためfalse
var foo = exists bar
// 変数fooが存在するためtrue
var bar = exists foo
リテラル式
AiScriptにおけるリテラルとは、値を文字列として書き表すための表記法です。
リテラルはスクリプト中でそのまま式として使用することができます。
null、真理値、数値、文字列、オブジェクト、関数のリテラルが存在しています。
null
null
真理値
true
false
数値
十進以外の記数法はサポートされていません。
12 // 自然数
-34 // 負数
52.448 // 小数
※負数を表す-
は数値リテラルのみで使用できます。-variable
のような表記はサポートされていません。
文字列
'
または"
が使用可能な通常の文字列リテラルと、`
を使用し文中に式を含むことができるテンプレートリテラルがあります。
エスケープについて
\
を前置した文字は、構文の一部ではなく一つの文字として解釈されます。
例えば'\''
は'
、
"\""
では"
、
`\``
は`
、
`\{`
は{
、として解釈されます。
特に構文としての意味を持たない文字の場合、単に\
が無視されます。例:'\n'
→ n
文字\
を使用したい場合は'\\'
のように2つ繋げてください。
エスケープシーケンスは未サポートです。
文字列リテラル
'ここでは"を文字列に含むことができます'
"ここでは'を文字列に含むことができます"
'エスケープすれば\'を含むことができます'
"エスケープすれば\"を含むことができます"
'改行
できます'
"改行 // ここにコメントを書くと文字列の一部になります
できます" // ここは問題なし
テンプレートリテラル
変数や式を埋め込んだ文字列を作成するためのリテラルです。
全体を` `
で囲い、式を埋め込む場所は{ }
で囲います。
式の値が文字列でない場合は、Core:to_strと同じ方法で文字列に変換されます。
<: `Ai chan is No.{ 2-1 }` // Ai chan is No.1
// 改行可 一行にしたい場合は{ Str:lf }を使う
`This statement is { true }.
Previous statement is { !true }.`
// \を前置することで`、{、}、をエスケープできる
`\` \{ \}` // ` { }
// { }の中身が空であってはならない({ }を文字列として使いたい場合はエスケープすること)
`Everything is { } here.` // Syntax Error
// 式の前後で改行をしてはならない(式中で改行するのは可)
`Oops, something went {
'wrong'
}!` // Syntax Error
配列
[] // 空の配列
[1, 1+1, 1+1+1] // コロンで区切ることも出来る
[1, 1+1, 1+1+1,] // 最後の項に,をつけてもよい
[ // 改行区切りも可
'hoge'
'huga'
'piyo'
]
[ // コロンと改行の併用可
'hoge',
'huga',
'piyo',
]
[1 2 3] // 空白区切りは廃止済み
オブジェクト
{} // 空のオブジェクト
{ // 改行区切り
a: 12
b: 'hoge'
}
{a: 12,b: 'hoge'} // コロン区切り
// 空白区切りは廃止済み
{a: 12 b: 'hoge'} // Syntax Error
// セミコロン区切りは廃止済み
{a: 12; b: 'hoge'} // Syntax Error
関数
関数のリテラルは「無名関数」と呼ばれており、関数の宣言とよく似た形をしていますが、関数名がありません。(そして、リテラルなので当然ながら、文ではなく式です)
var func = @(){} // 何もしない関数
// 最後の式が暗黙にreturnされる
func = @(x, y) {
x + y
}
<: func(1, 2) // 3
// 明示的にreturnを書くこともできる
@(x, y) {
return x + y
}
// 引数を複数行で書いてもよい
@(
x,
y
) {
x + y
}
@(x,y){x+y} // ワンライナー
エラー型
エラー型のリテラルはありませんが、Error:createで値を作ることができます。
予約語について
AiScriptにおける予約語とは、変数や関数の名前として使用することが禁止されている単語のことを言います。
使用するとSyntax Errorとなります。
// matchとforは予約語
let match=null // エラー
@for(){ print('hoge') } // エラー
使用中の語と使用予定の語
match
やfor
は文法中で既にキーワードとして使用されています。
もしこれらが変数名として使用されると、プログラムの見た目が紛らわしいものになるだけでなく、文法解析上のコストが増加します。
ゆえに文法中のキーワードは基本的に全て予約語となっています。
一方で、いくつかの単語は文法中に存在しないにも関わらず予約語となっています。
これは将来文法が拡張された時に使用される可能性を見越してのものです。
一覧
以下の単語が予約語として登録されています。
使用中の語
null
, true
, false
, each
, for
, loop
, break
, continue
, match
, case
, default
, if
, elif
, else
, return
, eval
, var
, let
, exists
使用予定の語
as
, async
, attr
, attribute
, await
, catch
, class
, component
, constructor
, dictionary
, do
, enum
, export
, finally
, fn
, hash
, in
, interface
, out
, private
, public
, ref
, static
, struct
, table
, this
, throw
, trait
, try
, undefined
, use
, using
, when
, while
, yield
, import
, is
, meta
, module
, namespace
, new
標準定数・標準関数について
Aiscriptで最初から定義されていてどこでも使える定数・関数を指します。
standardを省略してstd定数/関数とも呼ばれています。
書式
#Core:v
Core:v
という標準定数を表します。
@Core:type(v: value): str
Core:type
という標準関数を表します。
v
という名のvalue型(つまり任意の型)の引数を一つとり、str型(文字列型)の値を返します。
一覧
std
@print(message: str): void
画面に文字列を表示します。
@readline(message: str): str
文字列の入力を受け付けます。
:: Core
#Core:v
型: str
AiScriptのバージョンです。
@Core:type(v: value): str
値の型名を取得します。
@Core:to_str(v: value): str
値を表す文字列を取得します。
@Core:sleep(time: num): void
指定時間(ミリ秒)待機します。
@Core:abort(message: str): never
プログラムを緊急停止します。
:: Util
@Util:uuid(): str
新しいUUIDを生成します。
:: Json
@Json:stringify(v: value): str
JSONを生成します。
@Json:parse(json: str): value
JSONをパースします。 引数がJSONとしてパース可能性でない場合、エラー型の値(name
='not_json'
)を返します。
@Json:parsable(str: str): bool
文字列がJSONとしてパース可能であるかの判定を行います。歴史的理由により存在しています
:: Date
@Date:now(): num
現在時刻を取得します。
@Date:year(date?: num): num
時刻の年を取得します。
date を渡した場合、_date_に対応する年、
渡していない場合は現在時刻の年が返されます。
@Date:month(date?: num): num
現在時刻の月を取得します。
date を渡した場合、_date_に対応する月、
渡していない場合は現在時刻の月が返されます。
@Date:day(date?: num): num
現在時刻の日を取得します。
date を渡した場合、_date_に対応する日、
渡していない場合は現在時刻の日が返されます。
@Date:hour(date?: num): num
現在時刻の時を取得します。
date を渡した場合、_date_に対応する時、
渡していない場合は現在時刻の時が返されます。
@Date:minute(date?: num): num
現在時刻の分を取得します。
date を渡した場合、_date_に対応する分、
渡していない場合は現在時刻の分が返されます。
@Date:second(date?: num): num
現在時刻の秒を取得します。
date を渡した場合、_date_に対応する秒、
渡していない場合は現在時刻の秒が返されます。
@Date:millisecond(date?: num): num
現在時刻のミリ秒を取得します。
date を渡した場合、_date_に対応するミリ秒、
渡していない場合は現在時刻のミリ秒が返されます。
@Date:parse(date: str): num
日付として解釈可能な文字列から日時を表す数値を生成します。
解釈はJavaScriptのDateコンストラクターに依存します。
引数が日付として解釈可能でない場合、エラー型の値(name
='not_date'
)を返します。
@Date:to_iso_str(date?: num, time_offset?: num): str
date を拡張表記のISO形式にした文字列を返します。
date を渡していない場合は現在時刻を使用します。
time_offset はUTCからの時差(分単位)を指定します。
time_offset を渡していない場合はローカルのものを参照します。
:: Math
数が多いため専用のページになっています。→std-math.md
:: Num
@Num:from_hex(hex: str): num
16進数の文字列から数値を生成します。
:: Str
#Str:lf
型: str
改行コード(LF)です。
@Str:lt(a: str, b: str): num
a < b ならば -1、a == b ならば 0、a > b ならば 1 を返します。
arr.sortの比較関数として使用できます。
@Str:gt(a: str, b: str): num
a > b ならば -1、a == b ならば 0、a < b ならば 1 を返します。
arr.sortの比較関数として使用できます。
@Str:from_codepoint(codepoint: num): str
Unicodeのコードポイントから文字を生成します。
codepoint は 0 以上、10FFFF16 以下である必要があります。
@Str:from_unicode_codepoints(codePoints: arr<num>
): str
Unicodeのコードポイント列を表す数値の配列から文字を生成します。
_codePoints_の各要素は 0 以上、10FFFF16 以下である必要があります。
@Str:from_utf8_bytes(bytes: arr<num>
): str
UTF-8のバイト列を表す数値の配列から文字を生成します。
_bytes_の各要素は 0 以上、255 以下である必要があります。
:: Uri
@Uri:encode_full(uri: str): str
uri をURIとしてエンコードした文字列を返します。以下の文字はエンコードされません。
A-Z a-z 0-9 - _ . ! ~ * ' ( ) ; , / ? : @ & = + $ #
@Uri:encode_component(text: str): str
text をURI構成要素としてエンコードした文字列を返します。以下の文字はエンコードされません。
A-Z a-z 0-9 - _ . ! ~ * ' ( )
@Uri:decode_full(encoded_uri: str): str
encoded_uri をエンコードされたURIとしてデコードした文字列を返します。
以下の文字に対応するエスケープシーケンスはデコードされません。
; , / ? : @ & = + $ #
@Uri:decode_component(encoded_text: str): str
encoded_text をエンコードされたURI構成要素としてデコードした文字列を返します。
:: Arr
@Arr:create(length: num, initial?: value): arr
長さがlength
の配列を作成します。
配列は initial が与えられていれば initial 、でなければnull
で埋められます。
:: Obj
@Obj:keys(v: obj): arr
@Obj:vals(v: obj): arr
@Obj:kvs(v: obj): arr
オブジェクトのキー、値、キーと値の組を配列にして返します。
@Obj:get(v: obj, key: str): value
@Obj:set(v: obj, key: str, val: value): null
@Obj:has(v: obj, key: str): bool
@Obj:copy(v: obj): obj
オブジェクトのコピーを生成します。
@Obj:merge(o1: obj, o2: obj): obj
2つのオブジェクトを併合したものを返します。
:: Error
@Error:create(name: str, info?: value): error
エラー型の値を作成します。
:: Async
@Async:interval(interval: num, callback: fn, immediate?: bool): fn
指定した周期でコールバック関数を呼び出します。
戻り値として停止関数を返します。
@Async:timeout(delay: num, callback: fn):
指定した時間経過後にコールバック関数を呼び出します。
戻り値として停止関数を返します。
Math
数学・数値計算関連の標準定数・関数にはMath:
の名前空間が付与されています。
定数
型は全てnum
です。
定数名 | 説明 | 概算値 |
---|---|---|
Math:Infinity | 無限大 | なし |
Math:E | ネイピア数e | 2.718281828459045 |
Math:LN2 | 2の自然対数 | 0.6931471805599453 |
Math:LN10 | 10の自然対数 | 2.302585092994046 |
Math:LOG2E | 2を底としたeの対数 | 1.4426950408889634 |
Math:LOG10E | 10を底としたeの対数 | 0.4342944819032518 |
Math:PI | 円周率π | 3.141592653589793 |
Math:SQRT1_2 | √(1/2) | 0.7071067811865476 |
Math:SQRT2 | √2 | 1.4142135623730951 |
基本的な関数
@Math:abs(x: num): num
絶対値を計算します。
@Math:sign(x: num): num
x が正であれば1、負であれば-1、0または-0であればそのままの値を返します。
いずれでもなければNaNを返します。
@Math:round(x: num): num
四捨五入して、もっとも近い整数を返します。
@Math:ceil(x: num): num
引数以上の最小の整数を返します。
@Math:floor(x: num): num
引数以下の最大の整数を返します。
@Math:trunc(x: num): num
引数の小数部を切り捨て、整数部を返します。
@Math:min(a: num, b: num): num
小さい方の値を取得します。
@Math:max(a: num, b: num): num
大きい方の値を取得します。
@Math:sqrt(x: num): num
正の平方根を計算します。
@Math:cbrt(x: num): num
立方根を計算します。
@Math:hypot(vs: arr): num
vs の要素をそれぞれ自乗してから合計した値の正の平方根を返します。
三角関数
角度の単位はラジアンです。
@Math:sin(rad: num): num
正弦を計算します。
@Math:cos(rad: num): num
余弦を計算します。
@Math:tan(rad: num): num
正接を計算します。
@Math:asin(x: num): num
逆正弦を計算します。
@Math:acos(x: num): num
逆余弦を計算します。
@Math:atan(x: num): num
逆正接を計算します。
@Math:atan2(y: num, x: num): num
y /x の正接を返しますが、x が負値の場合はπだけずれた値を返します。
双曲線関数
@Math:sinh(x: num): num
双曲線正弦を計算します。
@Math:cosh(x: num): num
双曲線余弦を計算します。
@Math:tanh(x: num): num
双曲線正接を計算します。
@Math:asinh(x: num): num
双曲線逆正弦を計算します。
@Math:acosh(x: num): num
双曲線逆余弦を計算します。
@Math:atanh(x: num): num
双曲線逆正接を計算します。
指数・対数関数
@Math:pow(x: num, y: num): num
x の y 乗を計算します。内部的にJavascriptの**
演算子ではなくMath.pow
関数を用いている点を除き、ほぼCore:pow
と同じものです。
@Math:exp(x: num): num
eの x 乗を計算します。
@Math:expm1(x: num): num
eの x 乗から1を引いた値を計算します。
@Math:log(x: num): num
自然対数を計算します。常用対数にはMath:log10
を使用して下さい。
@Math:log1p(x: num): num
x +1の自然対数を計算します。
@Math:log10(x: num): num
10を底とした対数を計算します。
@Math:log2(x: num): num
2を底とした対数を計算します。
乱数
@Math:rnd(min?: num, max?: num): num
乱数を生成します。
min および max を渡した場合、min <= x, x <= max の整数、
渡していない場合は 0 <= x, x < 1 の 小数が返されます。
@Math:gen_rng(seed: num | str, options?: obj): @(min?: num, max?: num)
シードから乱数生成機を生成します。
生成された乱数生成器は、min および max を渡した場合、min <= x, x <= max の整数、
渡していない場合は 0 <= x, x < 1 の浮動小数点数を返します。
options に渡したオブジェクトを通じて、内部の挙動を指定できます。
options.algorithm
の指定による挙動の変化は下記の通りです。
options.algorithm | 内部の乱数生成アルゴリズム | 範囲指定整数生成アルゴリズム |
---|---|---|
rc4 | RC4 | Rejection Sampling |
rc4_legacy | RC4 | 浮動小数点数演算による範囲制限(0.19.0以前のアルゴリズム) |
無指定 または 'chacha20' | ChaCha20 | Rejection Sampling |
その他
@Math:clz32(x: num): num
xを32ビットのバイナリで表現したときの先頭の0の個数を返します。
@Math:fround(x: num): num
x を32ビットの浮動小数点数に変換した時の値を返します。
@Math:imul(x: num, y: num): num
x と y に対しC言語風の32ビット乗算を行った結果を返します。
組み込みプロパティとは、型ごとに用意された特殊な値あるいは関数です。
オブジェクトのプロパティのように.<name>
の記法で呼び出すことができます。([<str>]
の記法は使えません)
// 例
'ai kawaii'.len //9
Core:range(0,2).push(4) //[0,1,2,4]
今の所、数値・文字列・配列・エラー型に対応するものが用意されています。オブジェクトのそれに相当するものは、記法との兼ね合いでstd関数として実装されています。
書式
本ページでは、(型名)型の任意の値に対する組み込みプロパティを下記のような形式で表記します。
#(v: 型名).プロパティ名
// または
@(v: 型名).組み込みメソッド名(引数リスト): 返り値の型
#から始まるものは関数以外の値を持つ組み込みプロパティです。 @から始まるものは関数の組み込みプロパティ(組み込みメソッド)です。
数値
@(x: num).to_str(): str
数値を文字列に変換します。
@(x: num).to_hex(): str
数値から16進数の文字列を生成します。
文字列
#(v: str).len
型: num
文字列の長さを取得します。
@(v: str).to_num(): num | null
文字列が数字であれば、数値に変換します。
@(v: str).to_arr(): arr<str>
文字列を書記素クラスタ毎に区切り、配列にしたものを返します。
文字列に孤立サロゲートが含まれない場合、孤立サロゲートを返すことはありません。
@(v: str).to_unicode_arr(): arr<str>
文字列を Unicode コードポイント毎に区切り、配列にしたものを返します。
書記素クラスタは分割されます。
文字列に孤立サロゲートが含まれない場合、孤立サロゲートを返すことはありません。
@(v: str).to_unicode_codepoint_arr(): arr<num>
文字列を Unicode コードポイント毎に区切り、それぞれコードポイント値を取得し配列にしたものを返します。
文字列に孤立サロゲートが含まれない場合、孤立サロゲートを返すことはありません。
@(v: str).to_char_arr(): arr<str>
文字列を UTF-16 コード単位毎に区切り、配列にしたものを返します。
文字列にサロゲートペアが含まれる場合、上位と下位それぞれ孤立サロゲートを返します。
@(v: str).to_charcode_arr(): arr<num>
文字列を UTF-16 コード単位毎に区切り、それぞれUTF-16 コード単位を表す 0
から 65535
までの整数を取得し配列にしたものを返します。
文字列にサロゲートペアが含まれる場合、上位と下位それぞれ孤立サロゲートを返します。
@(v: str).to_utf8_byte_arr(): arr<num>
文字列を UTF-8 エンコードし、各バイト毎の 0
から 255
までの整数値を取得し配列にしたものを返します。
@(v: str).pick(i: num): str | null
文字列中の i 番目の文字を取得します。
@(v: str).incl(keyword: str): bool
文字列中に keyword が含まれていればtrue
、なければfalse
を返します。
@(v: str).starts_with(prefix: str, start_index?: num): bool
文字列が prefix で始まっていればtrue
、そうでなければfalse
を返します。
prefix が空文字列の場合は常にtrue
を返します。
start_index が指定されている場合、そのインデックスから始めます。
start_index がv.len
より大きいか-v.len
より小さい場合はfalse
を返します。
start_index が負の場合は末尾から数えます。
@(v: str).ends_with(suffix: str, end_index?: num): bool
文字列が suffix で終わっていればtrue
、そうでなければfalse
を返します。
suffix が空文字列の場合は常にtrue
を返します。
end_index が指定されている場合、そのインデックスの直前を末尾とします。(省略時はv.len
)
end_index がv.len
より大きいか-v.len
より小さい場合はfalse
を返します。
end_index が負の場合は末尾から数えます。
@(v: str).slice(begin: num, end: num): str
文字列の begin 番目から end 番目の直前までの部分を取得します。
@(v: str).split(splitter?: str): arr
文字列を splitter がある場所で区切り、配列にしたものを返します。
splitter が与えられなければ一文字づつ区切ります。
@(v: str).replace(old: str, new: str): str
文字列中の old を new に置換したものを返します。
@(v: str).index_of(search: str, fromIndex?: num): num
文字列中から_search_を探し、その添字を返します。
_fromIndex_が指定されていれば、その位置から検索を開始します。
_fromIndex_が負値の時は末尾からの位置(文字列の長さ+fromIndex)が使用されます。
該当が無ければ-1を返します。
@(v: str).pad_start(width: num, pad?: str): str
文字列の長さがが width になるように、先頭を pad の繰り返しで埋めた新しい文字列を返します。
pad を省略した場合、空白' '
で埋められます。
pad が長すぎる場合、pad の末尾が切り捨てられます。
@(v: str).pad_end(width: num, pad?: str): str
文字列の長さがが width になるように、末尾を pad の繰り返しで埋めた新しい文字列を返します。
pad を省略した場合、空白' '
で埋められます。
pad が長すぎる場合、pad の末尾が切り捨てられます。
@(v: str).trim(): str
文字列の前後の空白を取り除いたものを返します。
@(v: str).upper(): str
文字列中の英字を大文字に変換して返します。
@(v: str).lower(): str
文字列中の英字を小文字に変換して返します。
@(v: str).charcode_at(i: num): num | null
i 番目のにある UTF-16 コード単位を表す 0
から 65535
までの整数を返します。
インデックスは UTF-16 コード単位に基づきます。
文字列にサロゲートペアが含まれる場合、位置によって上位または下位の孤立サロゲートを返すことがあります。
i 番目の文字が存在しない場合は null が返されます。
@(v: str).codepoint_at(i: num): num | null
i 番目の文字のコードポイントを取得します。
インデックスは UTF-16 コード単位に基づきます。
文字列にサロゲートペアが含まれ、指定位置が下位のサロゲートである場合、下位の孤立サロゲートを返します。
i 番目の文字が存在しない場合は null が返されます。
配列
#(v: arr).len
型: num
配列の要素数を取得します。
@(v: arr).at(index: num, otherwise?: value): value
配列の index の位置の要素を返します。
index が負の場合は末尾から数えます。
index が範囲外の場合は、代わりに otherwise を返します。
otherwise が省略されている場合はnull
になります。
@(v: arr).push(i: value): null
【この操作は配列を書き換えます】
配列の最後に要素を追加します。
@(v: arr).unshift(i: value): null
【この操作は配列を書き換えます】
配列の最初に要素を追加します。
@(v: arr).pop(): value
【この操作は配列を書き換えます】
配列の最後の要素を取り出します。
@(v: arr).shift(): value
【この操作は配列を書き換えます】
配列の最初の要素を取り出します。
@(a: arr).concat(b: arr): arr
配列を連結します。
@(v: arr).join(joiner?: str): str
文字列の配列を結合して一つの文字列として返します。
@(v: arr).slice(begin: num, end: num): arr
配列の begin 番目から end 番目の部分を切り出して返します。
@(v: arr).incl(i: value): bool
配列に指定した値が含まれているかどうかを返します。
@(v: arr).map(func: fn): arr
配列の各要素に対し func を非同期的に呼び出します。 それぞれの要素を func の返り値で置き換えたものを返します。
@(v: arr).filter(func: fn): arr
配列の要素のうち func が true を返すようなもののみを抜き出して返します。
順序は維持されます。
@(v: arr).reduce(func: Callback, initial: value): value
Callback
: @(acm: value, item: value, index: num): value
配列の各要素に対し func を順番に呼び出します。
各呼び出しでは、前回の結果が第1引数 acm として渡されます。
initial が指定された場合は初回呼び出しの引数が(initial, v[0], 0)、
指定されなかった場合は(v[0], v[1], 1)となります。
配列が空配列であり、かつ initial が指定されていない場合はエラーになります。従って基本的には initial を指定しておくことが推奨されています。
@(v: arr).find(func: @(item: value, index: num) { bool }): value
配列から func が true を返すような要素を探し、その値を返します。
@(v: arr).index_of(val: value, fromIndex?: num): num
配列から_val_と同じ値を探し、その添字を返します。
_fromIndex_が指定されていれば、その位置から検索を開始します。
_fromIndex_が負値の時は末尾からの位置(配列の長さ+fromIndex)が使用されます。
該当が無ければ-1を返します。
@(v: arr).reverse(): null
【この操作は配列を書き換えます】
配列を反転させます。
@(v: arr).copy(): arr
配列のコピーを生成します。
シャローコピーであり、配列やオブジェクトの参照は維持されます。
@(v: arr).sort(comp: @(a: value, b: value)): arr
【この操作は配列を書き換えます】
配列の並べ替えをします。第1引数 comp として次のような比較関数を渡します。
安定ソートです。
- a が b より順番的に前の時、負の値を返す
- a が b より順番的に後の時、正の値を返す
- a が b と順番的に同等の時、0を返す
数値の並び替えではCore:sub
を渡すことで昇順、@(a,b){b-a}
を渡すことで降順ソートができます。
文字列用の比較関数としてStr:lt
(昇順), Str:gt
(降順)が用意されています。詳しくはstd.mdをご覧下さい。
@(v: arr).fill(val?: value, fromIndex?: num, toIndex?: num): arr
【この操作は配列を書き換えます】
配列の fromIndex から toIndex までの範囲の要素を val で置き換えます。
val 省略時はnull
で置き換えます。
fromIndex および toIndex に関する挙動はarr.slice
に準拠します。
@(v: arr).repeat(times: num): arr
配列を times 回繰り返した配列を作成します。
arr.copy
同様シャローコピーであり、配列やオブジェクトの参照は維持されます。
times には0以上の整数値を指定します。それ以外ではエラーになります。
@(v: arr).splice(index: num, remove_count?: num, items?: arr<value>): arr<value>
【この操作は配列を書き換えます】
配列の index から remove_count 個の要素を取り除き、その位置に items の要素を挿入します。
返り値として、取り除いた要素の配列を返します。
index が負の場合は末尾から数えます。
index が最後の要素より後の場合は要素を取り除かず、挿入は末尾に追加します。
remove_count を省略した場合、末尾まで取り除きます。
items を省略した場合、何も挿入しません。
@(v: arr).flat(depth?: num): arr
配列に含まれる配列を depth で指定した深さの階層まで結合した新しい配列を作成します。
depth には0以上の整数値を指定します。省略時は1になります。
@(v: arr).flat_map(func: @(item: value, index: num) { value }): arr
配列の各要素を func の返り値で置き換えた後、1階層平坦化した新しい配列を作成します。
func は非同期的に呼び出されます。
@(v: arr).insert(index: num, item: value): null
【この操作は配列を書き換えます】
配列の index の位置に item を挿入します。
index が負の場合は末尾から数えます。
index が最後の要素より後の場合は末尾に追加します。
@(v: arr).remove(index: num): value | null
【この操作は配列を書き換えます】
配列から index の位置の要素を取り除き、その要素を返します。
index が負の場合は末尾から数えます。
index が最後の要素より後の場合は取り除かず、null
を返します。
@(v: arr).every(func: @(item: value, index: num) { bool }): bool
配列の全ての要素に対して func が true を返す時のみ true 返します。空配列には常に true を返します。
@(v: arr).some(func: @(item: value, index: num) { bool }): bool
配列の要素に対して func が true を返す要素が存在する時のみ true 返します。
エラー型
#(v: error).name
型: str
エラーの識別子となる文字列を取得します。
#(v: error).info
型: value
エラーに付加情報がある場合、それを取得します。