浪語:修订间差异
Lambda.cat(留言 | 贡献) 无编辑摘要 标签:2017版源代码编辑 |
Lambda.cat(留言 | 贡献) 无编辑摘要 标签:2017版源代码编辑 |
||
(未显示2个用户的40个中间版本) | |||
第1行: | 第1行: | ||
一種 JavaScript 的方言,因為由浪打所創因而得名。 | 一種 JavaScript 的方言,因為由浪打所創因而得名。 | ||
目前你可以在浪打所作的[ | 目前你可以在浪打所作的 [[浪打聊天插件|聊天插件]] 上使用他。 | ||
[[File:Lambda language.png | 此手冊目前還有 [https://hackmd.io/@nobodyzxc/SkoZau-Qd/https%3A%2F%2Fhackmd.io%2FVKZIZxRJQ4yPT-FElCa1GQ HackMD 線上板手冊中文版](更好的閱讀體驗,但須翻牆) | ||
在 HackMD 上也有 [https://hackmd.io/@nobodyzxc/SkoZau-Qd/https%3A%2F%2Fhackmd.io%2F8tO-FVCJSCGpRPoRDd1Uig English Manual]. | |||
[[File:Lambda language.png|每三十秒使用一言 API 換一次部屋描述。|有框|链接=Special:FilePath/Lambda_language.png]] | |||
資料型態大概以下這些: | 資料型態大概以下這些: | ||
# Boolean (true/false) | #Boolean (true/false) | ||
# Number (-1/0/3.14) | #Number (-1/0/3.14) | ||
# String ("hello, lambda!") | #String ("hello, lambda!") | ||
# Array ([1,2,3,4]) | #Array ([1,2,3,4]) | ||
# Object ({x: 1.34, y: 4.5}) | #Object ({x: 1.34, y: 4.5}) | ||
# Function ((a, b) => a + b) | #Function ((a, b) => a + b) | ||
因為這個語言會直譯 | 因為這個語言會被 JavaScript 直譯, | ||
所以 JS 裡的物件其實都能在這個語言裡面進行構造、使用。 | 所以 JS 裡的物件其實都能在這個語言裡面進行構造、使用。 | ||
第27行: | 第31行: | ||
和 JS 不同的地方在於,浪語裡面所有東西都是 Expression,都一定有回傳值。 | 和 JS 不同的地方在於,浪語裡面所有東西都是 Expression,都一定有回傳值。 | ||
這個語言通常不會出現 undefined,取而代之的是,他回傳一個空物件 {}。 | 這個語言通常不會出現 undefined,取而代之的是,他回傳一個<s>空物件 {}</s> false。 | ||
分號 (;) 基本上都可以省略,或者你可以使用分號回傳一個空物件。 | 分號 (;) 基本上都可以省略,或者你可以使用分號回傳<s>一個空物件</s> false。 | ||
所有第一次參考到的變數,如果不存在,便會以空物件創建。 | 所有第一次參考到的變數,如果不存在,便會<s>以空物件創建</s> 是 false。 | ||
<syntaxhighlight lang="javascript" line="1"> | <syntaxhighlight lang="javascript" line="1"> | ||
print(x) | print(x) | ||
// not defined, show {} | // not defined, show false (before v1.740 is {}, false after v1.740) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
第40行: | 第44行: | ||
<syntaxhighlight lang="javascript" line="1"> | <syntaxhighlight lang="javascript" line="1"> | ||
fetch("https://v1.hitokoto.cn") | fetch("https://v1.hitokoto.cn") | ||
.then(response => response.json()) | |||
.then(result => { | .then(result => { | ||
print(result.hitokoto); | print(result.hitokoto); | ||
}); | }); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
※ <s>測試姬 /baka yande.re 指令復現</s>(nsfw 警告) | |||
<span style="color:black; background-color:black">event[me,msg](u,m:"^/baka yande.re")=>$.get("<nowiki>https://yande.re/post.json?limit=1&page=</nowiki>"+Math.floor(Math.random()*1e4),d=>drrr.dm(u,".",d[0].preview_url))</span> | |||
基本的 +, -, *, / 運算子都有支援,+=, ++, -- 之類的也有,但目前不支援三元運算子。 | 基本的 +, -, *, / 運算子都有支援,+=, ++, -- 之類的也有,但目前不支援三元運算子。 | ||
第75行: | 第84行: | ||
<syntaxhighlight lang="javascript" line="1"> | <syntaxhighlight lang="javascript" line="1"> | ||
f = (x) => | f = (x) => | ||
if | if x <= 0 then 0 | ||
else if | else if x == 1 then 1 | ||
else f(x - 1) + f(x - 2) | else f(x - 1) + f(x - 2) | ||
第112行: | 第121行: | ||
drrr.play("關鍵字", "音源", "數字") | drrr.play("關鍵字", "音源", "數字") | ||
// 後兩個參數是選擇性,和插件的 play 一樣。 | // 後兩個參數是選擇性,和插件的 play 一樣。 | ||
// 可以綁定以下 event 供使用者調用 | |||
event msg (user, msg: "^/play") => { | |||
word = argfmt(["$[1-]"], user, msg)[0] | |||
drrr.play(word) | |||
} | |||
drrr.join("房間 ID") | drrr.join("房間 ID") | ||
第119行: | 第134行: | ||
// 還有一些幫你抓好的變數 | // 還有一些幫你抓好的變數 | ||
loc // 現在位置(大廳或房間 "lounge" / "room") | drrr.loc // 現在位置(大廳或房間 "lounge" / "room") | ||
profile // 個人訊息 | drrr.profile // 個人訊息 | ||
room // 房間訊息 | drrr.room // 房間訊息 | ||
users // 房間成員 | drrr.users // 房間成員 | ||
info // 跟個人訊息有點像 | drrr.info // 跟個人訊息有點像 | ||
rooms // 所有房間,大廳狀態 | drrr.rooms // 所有房間,大廳狀態 | ||
// 有時你會需要更新,可以透過以下函數去更新他們 | // 有時你會需要更新,可以透過以下函數去更新他們 | ||
drrr.getLounge(callback); | |||
drrr.getProfile(callback); | |||
drrr.getLoc(callback); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
第143行: | 第158行: | ||
<syntaxhighlight lang="javascript" line="1"> | <syntaxhighlight lang="javascript" line="1"> | ||
state welcome { | state welcome { | ||
print("hello world"); | |||
going bye | going bye | ||
} | } | ||
state bye { | state bye { | ||
print("bye"); | |||
// done. | // done. | ||
} | } | ||
第157行: | 第172行: | ||
<syntaxhighlight lang="javascript" line="1"> | <syntaxhighlight lang="javascript" line="1"> | ||
state welcome { | state welcome { | ||
print("hello world"); | |||
going bye | going bye | ||
} | } | ||
state bye { | state bye { | ||
print("bye"); | |||
// because "visit welcome", so back to visit | // because "visit welcome", so back to visit | ||
} | } | ||
第177行: | 第192行: | ||
// 冒號 (:) 後面是 RegExp,如果匹配才呼叫。 | // 冒號 (:) 後面是 RegExp,如果匹配才呼叫。 | ||
// 適用於 user 和 content (第一和第二個參數) | // 適用於 user 和 content (第一和第二個參數) | ||
event msg (user: "lambda", content, url, tripcode, req){ | event msg (user: "lambda", content, url, tripcode, req) => { | ||
drrr.print(user | drrr.print(user + " 叫了一下"); | ||
} | } | ||
// 參數個數和名稱都可以任意,看你需求 | // 參數個數和名稱都可以任意,看你需求 | ||
event join (user){ | event join (user) => { | ||
drrr.print("welcome " + user); | drrr.print("welcome " + user); | ||
} | } | ||
第205行: | 第220行: | ||
} | } | ||
// | // parse error, 10000() is not a function call | ||
timer 10000 () => { | timer 10000 () => { | ||
print("hello world"); | print("hello world"); | ||
第216行: | 第231行: | ||
<syntaxhighlight lang="javascript" line="1"> | <syntaxhighlight lang="javascript" line="1"> | ||
later 10000 print("hello world") | later 10000 print("hello world") | ||
// 注意以下 function 不會被呼叫 | |||
f = () => console.log("hello world") | |||
later 3000 f // 不會被呼叫,因為 f 被 auto lift,又被包了一層 function 在外面 | |||
later 3000 f() // 這樣才會在三秒後印出 hello world | |||
later 3000 () => console.log("hello world") // parse error, 3000() is not a function call | |||
later 3000; () => console.log("hello world") // works, good | |||
later 3000; (a, b) => console.log("hello world") // fine, too | |||
later 3000 console.log("hello world") // 這個也會正常運作 | |||
later 3000 { | |||
console.log("hello world") // 這個也會正常運作 | |||
} | |||
</syntaxhighlight> | |||
※ 注意 timer 和 later 會將 "非 lambda 的 expression" lift 成一個 lambda expression,然後時間到了再 eval 他。 | |||
一些功能實作: | |||
歡迎回來功能: | |||
<syntaxhighlight lang="javascript" line="1"> | |||
guests = drrr.users.map((x)=>x.name); | |||
event join (user) => { | |||
if guests.includes(user) | |||
then drrr.print("welcome back, " + user) | |||
else guests.push(user) | |||
} | |||
print(guests) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
猜數字遊戲: | |||
<syntaxhighlight lang="javascript" line="1"> | |||
valid = (digits) => | |||
(new Set(digits.split(""))).size === 4 | |||
generate = () => { | |||
while(!valid(digits = String(Math.floor(1000 + Math.random() * 9000)))); | |||
digits | |||
} | |||
gnjdg = (guess, callback) => { | |||
if(valid(guess)) then { | |||
d = theNumber.split("") | |||
g = guess.split("") | |||
c = g.map((v)=>d.includes(v)).reduce((a, b)=>a+b) | |||
a = g.map((v, idx)=>d[idx] === g[idx]).reduce((a, b)=>a+b) | |||
b = c - a | |||
callback( | |||
if(a === 4) then | |||
"Your Number is Correct" | |||
else | |||
guess + ":" + String(a) + "A" + String(b) + "B" | |||
) | |||
} else callback("guess number must be 4 non-repeat digits" + guess); | |||
} | |||
theNumber = generate() | |||
event msg (user, cont: "^\\d\\d\\d\\d$") => gnjdg(cont, drrr.print) | |||
event msg (user, cont: "^new$") => theNumber = generate() | |||
event msg (user, cont: "^ans$") => drrr.print(theNumber) | |||
</syntaxhighlight> | |||
歡迎貴賓: | |||
<syntaxhighlight lang="javascript" line="1"> | |||
// 房間上限 9.0001 人 | |||
event join (user) => { | |||
if drrr.users.length == 10 | |||
then | |||
drrr.print("/me恭喜成為 0.0001 人,你終於不做人類了嗎!"); | |||
else | |||
drrr.print("/me歡迎第 " + String(drrr.users.length) + " 個貴賓!"); | |||
} | |||
</syntaxhighlight> | |||
====套件管理器==== | |||
可以用套件管理導入 | |||
也可以 fork 一份 bs-pkgs 維護一個 mirror, | |||
然後透過 <code>add_mirror(alias, repo)</code> 來添加你的 mirror。 | |||
或者直接呼叫也行 | |||
要刪除的話就呼叫 <code>del_mirror(alias)</code>。[[File:選擇mirror.png|左|有框|選擇 mirror 後,點選 update 更新套件索引。之後可以選擇分類和套件,可以把他載入到編輯器或是儲存到本地。|链接=Special:FilePath/選擇mirror.png]] | |||
<br /> | |||
[[File:本地套件.png|左|有框|本地的套件句選後,可以選擇預載入,或是刪除。重新開啟視窗,如果是有句選,就代表為預載入套件。|链接=Special:FilePath/本地套件.png]] | |||
[[File:預載套件.png|左|有框|確定預載入後,在編輯器以套件名作為函數調用。(套件通常會提供這個函數,但具體還是要看套件內容定義)|链接=Special:FilePath/預載套件.png]] | |||
<br />[[File:Script 剛完成的傳教活動.png|链接=Special:FilePath/Script_剛完成的傳教活動.png|左|有框]]<br /> |
2021年12月2日 (四) 22:30的最新版本
一种 JavaScript 的方言,因为由浪打所创因而得名。
目前你可以在浪打所作的 聊天插件 上使用他。
此手册目前还有 HackMD 线上板手册中文版(更好的阅读体验,但须翻墙)
在 HackMD 上也有 English Manual.
资料型态大概以下这些:
- Boolean (true/false)
- Number (-1/0/3.14)
- String ("hello, lambda!")
- Array ([1,2,3,4])
- Object ({x: 1.34, y: 4.5})
- Function ((a, b) => a + b)
因为这个语言会被 JavaScript 直译,
所以 JS 里的物件其实都能在这个语言里面进行构造、使用。
由于参考到 JS 的 globalThis,所以你也可以直接使用 global 里面的东西。
console.log("hello world");
alert("it's a alert!");
和 JS 不同的地方在于,浪语里面所有东西都是 Expression,都一定有回传值。
这个语言通常不会出现 undefined,取而代之的是,他回传一个空物件 {} false。
分号 (;) 基本上都可以省略,或者你可以使用分号回传一个空物件 false。
所有第一次参考到的变数,如果不存在,便会以空物件创建 是 false。
print(x)
// not defined, show false (before v1.740 is {}, false after v1.740)
这个语言也可以发 ajax,可以实作一些有趣的功能。
fetch("https://v1.hitokoto.cn")
.then(response => response.json())
.then(result => {
print(result.hitokoto);
});
※ 测试姬 /baka yande.re 指令复现(nsfw 警告)
event[me,msg](u,m:"^/baka yande.re")=>$.get("https://yande.re/post.json?limit=1&page="+Math.floor(Math.random()*1e4),d=>drrr.dm(u,".",d[0].preview_url))
基本的 +, -, *, / 运算子都有支援,+=, ++, -- 之类的也有,但目前不支援三元运算子。
目前支援 if else 语法,但 switch 没有支援。
回圈语法支援 while, for loop, for in, for of,基本上和 JS 一样,但没有 do while。
回圈的小括弧可以省略。
// for(i = 0; i < 10; i++) is also good
for i = 0
i < 10
i++
print(i)
j = 0
while(j < 3){
print(j);
j++;
}
for(i of [1,2,3,4]) print(i);
for(j in {tom: 1, allen: 2}) print(j);
没有支援 function 语法,仅支援 arrow function,预设回传最后一个 expression。
f = (x) =>
if x <= 0 then 0
else if x == 1 then 1
else f(x - 1) + f(x - 2)
[0, 1, 2, 3, 4, 5, 6].map(f)
// => [0,1,1,2,3,5,8]
Scope ({}) 如果被当作参数,或者是 right value 绑定时,会被 lift 成没有参数的 function。
f = (a, b) => a + b;
print(f(1, 4)) // 5
g = { args[0] + args[1] };
print(g(1, 2)) // 3
跟 js 的 arguments 一样,在 function 或是 lifted scope 中,浪语的 args 可以拿到参数列。
我提供了一些和 drrr 有关的 function,绑定在 drrr 这个物件中。
drrr.title("設定部屋名稱")
drrr.descr("設定部屋描述")
drrr.print("發送訊息")
drrr.dm("人名", "私訊訊息")
drrr.chown("人名") // 更換房主
drrr.leave() // 離開部屋
drrr.play("關鍵字", "音源", "數字")
// 後兩個參數是選擇性,和插件的 play 一樣。
// 可以綁定以下 event 供使用者調用
event msg (user, msg: "^/play") => {
word = argfmt(["$[1-]"], user, msg)[0]
drrr.play(word)
}
drrr.join("房間 ID")
drrr.create("房間名稱", "房間描述", 房間人數:數字, "語系")
// 基本上都有預設參數,所以要傳幾個參數都行
// 還有一些幫你抓好的變數
drrr.loc // 現在位置(大廳或房間 "lounge" / "room")
drrr.profile // 個人訊息
drrr.room // 房間訊息
drrr.users // 房間成員
drrr.info // 跟個人訊息有點像
drrr.rooms // 所有房間,大廳狀態
// 有時你會需要更新,可以透過以下函數去更新他們
drrr.getLounge(callback);
drrr.getProfile(callback);
drrr.getLoc(callback);
目前浪语里,除了先前提到的保留字外,还有一些特殊的关键字:
- state 宣告一个 state,与 going 搭配使用,有自己的 scope。
但 going 是直接跳去那个地方不会回来。
如果你要回来的话,请使用 visit。
state welcome {
print("hello world");
going bye
}
state bye {
print("bye");
// done.
}
going welcome
state welcome {
print("hello world");
going bye
}
state bye {
print("bye");
// because "visit welcome", so back to visit
}
visit welcome
// back from bye
print("done");
// done.
- event 处理相关事件,event 种类和 event action 里的说明一样。
// 冒號 (:) 後面是 RegExp,如果匹配才呼叫。
// 適用於 user 和 content (第一和第二個參數)
event msg (user: "lambda", content, url, tripcode, req) => {
drrr.print(user + " 叫了一下");
}
// 參數個數和名稱都可以任意,看你需求
event join (user) => {
drrr.print("welcome " + user);
}
- timer 用于定时执行 function。
// 單位是 ms,所以 10000 是十秒
timer 10000 print("hello world"); // print 會被自動 lift 成 function
// 三十秒使用一言換一次部屋描述
timer 30000 fetch("https://v1.hitokoto.cn")
.then(response => response.json())
.then(result => {
drrr.descr(result.hitokoto);
});
// 等價於第一個範例
timer 10000 {
print("hello world");
}
// parse error, 10000() is not a function call
timer 10000 () => {
print("hello world");
}
- later 用于延迟执行 function,和 timer 很像,但是只执行一次。
later 10000 print("hello world")
// 注意以下 function 不會被呼叫
f = () => console.log("hello world")
later 3000 f // 不會被呼叫,因為 f 被 auto lift,又被包了一層 function 在外面
later 3000 f() // 這樣才會在三秒後印出 hello world
later 3000 () => console.log("hello world") // parse error, 3000() is not a function call
later 3000; () => console.log("hello world") // works, good
later 3000; (a, b) => console.log("hello world") // fine, too
later 3000 console.log("hello world") // 這個也會正常運作
later 3000 {
console.log("hello world") // 這個也會正常運作
}
※ 注意 timer 和 later 会将 "非 lambda 的 expression" lift 成一个 lambda expression,然后时间到了再 eval 他。
一些功能实作:
欢迎回来功能:
guests = drrr.users.map((x)=>x.name);
event join (user) => {
if guests.includes(user)
then drrr.print("welcome back, " + user)
else guests.push(user)
}
print(guests)
猜数字游戏:
valid = (digits) =>
(new Set(digits.split(""))).size === 4
generate = () => {
while(!valid(digits = String(Math.floor(1000 + Math.random() * 9000))));
digits
}
gnjdg = (guess, callback) => {
if(valid(guess)) then {
d = theNumber.split("")
g = guess.split("")
c = g.map((v)=>d.includes(v)).reduce((a, b)=>a+b)
a = g.map((v, idx)=>d[idx] === g[idx]).reduce((a, b)=>a+b)
b = c - a
callback(
if(a === 4) then
"Your Number is Correct"
else
guess + ":" + String(a) + "A" + String(b) + "B"
)
} else callback("guess number must be 4 non-repeat digits" + guess);
}
theNumber = generate()
event msg (user, cont: "^\\d\\d\\d\\d$") => gnjdg(cont, drrr.print)
event msg (user, cont: "^new$") => theNumber = generate()
event msg (user, cont: "^ans$") => drrr.print(theNumber)
欢迎贵宾:
// 房間上限 9.0001 人
event join (user) => {
if drrr.users.length == 10
then
drrr.print("/me恭喜成為 0.0001 人,你終於不做人類了嗎!");
else
drrr.print("/me歡迎第 " + String(drrr.users.length) + " 個貴賓!");
}
套件管理器
可以用套件管理导入
也可以 fork 一份 bs-pkgs 维护一个 mirror,
然后透过 add_mirror(alias, repo)
来添加你的 mirror。
或者直接呼叫也行
要删除的话就呼叫 del_mirror(alias)
。