文件由机器翻译+人工校对
格式是。医学博士
中的字符是代码
没有翻译,直接复制原文 以后会发在 github和 gitee
Scarpet API文档
#scarpet编程语言的基本组成部分。
Scarpet是一种编程语言
旨在提供编写自定义程序以在Minecraft中运行的能力
与世界互动。
本规范分为两部分:这一部分对任何人都是不可知的
与布雷艇相关的特征和功能,以及
用于特定的雷击程序和世界操纵功能。
#概要
<pre>
script run print(‘Hello World!’)
</pre>
或者一个过于复杂的例子:
<pre>
/script run
block_check(x1, y1, z1, x2, y2, z2, block_to_check) ->
(
l(minx, maxx) = sort(l(x1, x2));
l(miny, maxy) = sort(l(y1, y2));
l(minz, maxz) = sort(l(z1, z2));
‘Need to compute the size of the area of course’;
‘Cause this language doesn\’t support comments in the command mode’;
xsize = maxx – minx + 1;
ysize = maxy – miny + 1;
zsize = maxz – minz + 1;
total_count = 0;
loop(xsize,
xx = minx + _ ;
loop(ysize,
yy = miny + _ ;
loop(zsize,
zz = minz + _ ;
if ( block(xx,yy,zz) == block_to_check,
total_count += ceil(rand(1))
)
)
)
);
total_count
);
check_area_around_closest_player_for_block(block_to_check) ->
(
closest_player = player();
l(posx, posy, posz) = query(closest_player, ‘pos’);
total_count = block_check( posx-8,1,posz-8, posx+8,17,posz+8, block_to_check);
print(‘There is ‘+total_count+’ of ‘+block_to_check+’ around you’)
)
/script invoke check_area_around_closest_player_for_block ‘diamond_ore’
</pre>
或者只是
<pre>
/script run print(‘There is ‘+for(rect(x,9,z,8,8,8), _ == ‘diamond_ore’)+’ diamond ore around you’)
</pre>
检查更高级别的`scarpet`函数必须提供哪些功能是值得的。
#程序
你可以把程序想象成一个数学表达式,比如`2.4*sin(45)/(2-4)“或者`sin(y)>0&max(z,3)>3“。
写一个程序,就像写一个`2+3`,只是长一点。
##基本语言组件
程序由常量组成,如`2`,`3.14`,`pi`,或`foo`,运算符,如`+`,`/`,`->`,这些变量
可以定义,比如`foo`或将为您定义的特殊对象,比如`x`或`x`,我为每个
内置函数,以及具有名称的函数,参数形式为`f(a,b,c)`,其中`f`是函数名,
和`a,b,c`是可以是任何其他表达式的参数。这就是语言的全部,也是全部
总之-听起来很简单。
##代码流
像任何其他合适的编程语言一样,`scarpet`需要括号,基本上用来标识东西的开始和结束
结束的地方。在使用更复杂结构的语言中,比如Java,它们倾向于使用各种类型的
它们,圆的表示函数调用,花的表示代码段,正方形表示访问列表,尖的表示
泛型类型等。。。我的意思是-没有etc,因为他们已经用尽了所有的括号选项。。。
`Scarpet是不同的,因为它运行的一切都基于函数(虽然它本身不是函数)
语言(如lisp)只需要圆括号,一切都由程序员来组织
它的代码是可读的,因为添加更多的括号对程序的性能没有任何影响
因为它们是在执行之前编译的。请看下面的`if()`函数用法示例:
<pre>
if(x<y+6,set(x,8+y,z,’air’);plop(x,top(‘surface’,x,z),z,’birch’),sin(query(player(),’yaw’))>0.5,plop(0,0,0,’boulder’),particle(‘fire’,x,y,z))
</pre>
你喜欢看书吗
<pre>
if( x<y+6,
set(x,8+y,z,’air’);
plop(x,top(‘surface’,x,z),z,’birch’),
sin(query(player(),’yaw’))>0.5,
plop(0,0,0,’boulder’),
particle(‘fire’,x,y,z)
)
</pre>
或者更确切地说:
<pre>
if
( x<y+6,
(
set(x,8+y,z,’air’);
plop(x,top(‘surface’,x,z),z,’birch’)
),
// else if
sin(query(player(),’yaw’))>0.5,
(
plop(0,0,0,’boulder’)
),
// else
particle(‘fire’,x,y,z)
)
</pre>
不管你喜欢哪种款式都无所谓。这通常取决于形势和问题的复杂性
子组件。无论您添加多少空格和额外的方括号,代码的计算结果都将完全相同
相同的表达式,并且将运行完全相同的程序,所以请确保您的程序是好的和干净的,这样其他人就不会
有问题吗
##功能和范围
用户可以以`fun(args….)->expression`的形式定义函数,并对其进行编译和保存,以备将来使用
在这个执行过程中,还可以后续调用/script命令,添加到事件等函数
分配给变量,
作为参数传递,用`call(`fun`,args…)`函数调用,但在大多数情况下
直接打电话给他们
名称,格式为`fun(args…)`。这意味着,一旦定义了函数,就可以与世界一起保存
进一步使用。对于变量,有两种类型,全局的-在代码的任何地方共享,
这些都是以`global`开头的名字,还有局部变量,其他的都是
仅在每个函数内部可见。这也意味着函数中的所有参数都是
`按值传递`,而不是`按引用传递`。
##外部变量
通过将变量添加到函数签名包中,函数仍然可以从外部作用域`借用`变量
围绕内置函数`outer`。它将指定的值添加到函数调用堆栈中,使它们的行为完全一致
类似于在Java中捕获lambda,但与Java不同,捕获的变量不需要是final。斯卡佩特会
在函数定义时附加它们的新值,即使它们以后会更改。最有价值的是
复制但可变的值,如映射或列表,允许保留函数的`状态`,允许它们
有记忆,可以说像物体一样行动。有关详细信息,请选中`outer(var)`。
##代码传递,行指示符
请注意,这应该只适用于粘贴要用commandblock执行的代码。Scarpet建议
应用程序中的代码(扩展名为`.sc`的文件,可以放在world files中的`/scripts`文件夹中)
或者作为一个全球可用的应用程序在singleplayer中的`.minecraft/config/carpet/scripts`文件夹中加载
作为带有命令`/script load[app name]`的Scarpet应用程序。从磁盘加载的Scarpet应用程序只应
包含代码,不需要以`/script run`前缀开头。
以下是可以在world`/scripts`文件夹中的`foo.sc` app文件中提供的代码
<pre>
run_program() -> (
loop( 10,
// looping 10 times
// comments are allowed in scripts located in world files
// since we can tell where that line ends
foo = floor(rand(10));
check_not_zero(foo);
print(_+’ – foo: ‘+foo);
print(‘ reciprocal: ‘+ _/foo )
)
);
check_not_zero(foo) -> (
if (foo==0, foo = 1)
)
</pre>
我们称之为游戏中的:
<pre>
/script load foo
/script in foo invoke run_program
</pre>
但是,以下代码也可以作为命令或命令块输入。
由于可以输入聊天室的最大命令长度有限,因此您可能需要插入
通过将它们粘贴到命令块或从世界文件中读取来执行程序,但是粘贴到命令块将
删除一些空白并压扁新行,使代码不可读。如果您粘贴的程序
是完美的,永远不会造成错误,我向你致敬,但在大多数情况下,它很可能是你的程序
可能会在编译时(最初分析时)或执行时(突然尝试
把某物除以零。在这些情况下,您可能希望得到一条有意义的错误消息,但为此,您需要
需要为编译器指出这些新行放在哪里,因为命令块会压扁它们。为此,
放在行的开头,让编译器知道您在哪里。这使得`$`是唯一的
在程序中是非法的字符,因为它将被替换为新行。据我所知,`$`不是
在Minecraft标识符中的任何地方使用,所以这不应该妨碍你程序的能力。
考虑以下作为命令块命令执行的程序:
<pre>
/script run
run_program() -> (
loop(10,
foo=地板(rand());
check_not_zero(foo);
print(`+`-foo:`+foo`);
print(`交互:`+0/foo)
)
);
check_not_zero(foo)->(
if (foo==0,foo=1)
)
</pre>
假设其目的是检查条是否为零,并防止在打印时被零除,但因为
`foo`作为变量传递,它从不更改原始foo值。因为不可避免的分裂
到0,我们得到以下信息:
<pre>
Your math is wrong, Incorrect number format for NaN at pos 98
run_program() -> ( loop( 10, foo = floor(rand(_)); check_not_zero(foo); print(_+’ – foo: ‘+foo);
HERE>> print(‘ reciprocal: ‘+ _/foo ) ));check_not_zero(foo) -> ( if (foo==0, foo = 1))
</pre>
如我们所见,我们得到的问题,数学运算的结果不是一个数字
(无穷大,所以不是一个数字),但是通过将我们的程序粘贴到命令中,使它如此压缩换行符
虽然很清楚错误发生在哪里,我们仍然可以跟踪错误,但是错误的位置(98)
是不是很有帮助,也不会有用,如果该程序得到显着更长。为了解决这个问题,我们可以
在脚本的每一行前面加上美元符号`$`:
<pre>
/script run
$run_program() -> (
$ loop( 10,
$ foo = floor(rand(_));
$ check_not_zero(foo);
$ print(_+’ – foo: ‘+foo);
$ print(‘ reciprocal: ‘+ _/foo )
$ )
$);
$check_not_zero(foo) -> (
$ if (foo==0, foo = 1)
$)
</pre>
然后我们得到以下错误消息
<pre>
Your math is wrong, Incorrect number format for NaN at line 7, pos 2
print(_+’ – foo: ‘+foo);
HERE>> print(‘ reciprocal: ‘+ _/foo )
)
</pre>
正如我们所注意到的,我们不仅得到了更简洁的片段,还得到了关于行号和位置的信息,
所以这意味着它更容易找到潜在的问题
显然这不是我们计划的工作方式。要通过函数调用修改foo,
我们要么返回结果并将其赋给新变量:
<pre>
foo = check_not_zero(foo);
…
check_not_zero(foo) -> if(foo == 0, 1, foo)
</pre>
.. 或者将其转换为全局变量,在本例中,不需要将其作为参数传递
<pre>
global_foo = floor(rand(10));
check_foo_not_zero();
…
check_foo_not_zero() -> if(global_foo == 0, global_foo = 1)
</pre>
##Scarpet预处理器
有几个预处理操作应用于程序的源代码,以清理它并准备
执行。其中一些会影响您的代码,因为它是通过堆栈跟踪和函数定义报告的,还有一些
仅适用于表面。
-剥离`//`注释(在文件模式下)
-用换行符替换`$`(在命令模式下,修改提交的代码)
-删除不跟在`;`后面的分号用作二进制运算符,允许轻松使用分号
-将`{`翻译成`m(`,`[`翻译成`l(`,`]`和`}`翻译成`)`
当前没有对代码应用进一步的优化。
##提到
LR1解析器,标记器和几个内置函数都是基于EvalEx项目构建的。
EvalEx是一个方便的Java表达式计算器,它允许
简单的数学和布尔表达式。EvalEx是在麻省理工学院许可下发行的。
#变量和常量
`scarpet `提供了许多可以在脚本中直接使用的常量
*`null`:没什么,zilch,甚至不假
*`true`:纯true,可以充当`1“
*`假`:假真或真假等于 `0` `
*‘pi’:对于周长的扇子来说,它是直径为1的苹果pi的周长。约3.14
*欧拉:聪明的家伙。其指数的导数为1\。约2.72
除此之外,还有一堆系统变量,以“开头,由“scarpet`内置设置,
像“`,通常是循环中的每个连续值,“i`表示迭代,或者“a`像累加器
用于`reduce`函数。对Minecraft特定调用的某些调用也会设置` x`,` y`,` z`,表示
封锁阵地。所有以“开头的变量都是只读的,不能在客户机代码中声明和修改。
##文字
`scarpet`接受数字和字符串常量。数字看起来像`1,2.5,-3e-7,0xff,`并且是内部的
主要表示为Java的`double`,但是`scarpet`会尽可能地修剪尾随的零,所以如果
需要将它们用作整数甚至长-你可以。长值也不会失去它们的长精度,
减法,求反和乘法,但是不能保证返回长值的任何其他运算
(如除法)在一个数字上,即使它可以适当地
表示为long,将使它们转换为double。
字符串使用单引号有多种原因,但主要是为了允许
在双引号命令参数中更容易使用字符串(将脚本作为`/script fill`的参数传递时)
例如),或者在scarpet中输入json(例如反馈到`/data merge`命令中)。
在普通字符串和正则表达式中,字符串还使用反斜杠`\`来引用特殊字符
<pre>
‘foo’
print(‘This doesn\’t work’)
nbt ~ ‘\\.foo’ // matching ‘.’ as a ‘.’, not ‘any character match’
</pre>
#操作员
在表达式中可以使用许多运算符。这些可以被视为泛型类型运算符
适用于大多数数据类型。它们还遵循标准运算符优先级,即理解`2+2*2`
作为`2+(2*2)`,而不是`(2+2)*2`,否则从左到右应用,即解释`2+4-3`
作为`(2+4)-3`,这在数字的情况下并不重要,但是因为“scarpet`允许混合所有值类型
关联性很重要,可能会导致意外的影响:
重要的运算符是函数定义`->`运算符。它将被覆盖
在[用户定义函数和程序控制流](docs/scarpet/language/Functions和controlflow.md)中
<pre>
‘123’+4-2 => (‘123’+4)-2 => ‘1234’-2 => ‘134’
‘123’+(4-2) => ‘123’+2 => ‘1232’
3*’foo’ => ‘foofoofoo’
1357-5 => 1352
1357-‘5’ => 137
3*’foo’-‘o’ => ‘fff’
[1,3,5]+7 => [8,10,12]
</pre>
如您所见,在同一表达式中与其他类型混合时,值的行为可能不同。
如果值的类型相同,结果往往很明显,但`Scarpet`试图理解任何东西
它必须处理
##运算符优先级
下面是`scarpet`中操作符的完整列表,包括控制流操作符。注意,逗号和括号
从技术上讲,它们不是运算符,而是语言的一部分,即使它们看起来像:
*匹配,获取`~:`
*一元`+-`
*指数`^`
*乘法`*/%`
*加法`+-`
*比较`>>=<=<`
*平等`===`
*逻辑与`&&`
*逻辑或`||`
*作业`=+=<>`
*定义`->`
*下一个语句“
*逗号“
*括号`()`
### `Get,访问器运算符:`
`get(…)`函数的运算符版本,用于访问列表,映射和其他容器的元素
(即NBTs)。区分`~`运算符很重要,它是一个匹配运算符,期望
执行一些额外的计算来检索结果,而`:`应该是直接的,即时的,并且
源对象的行为应类似于容器,并支持完整容器API,
表示`get(…)“,`put(…)“,`delete(…)“和`has(…)`函数`
对于某些运算符和函数(get,put,delete,has,=,+=),对象可以使用`:`注释字段作为l值,
意构式`foo:0 = 5`,类似于`put(foo,0,5)`,而不是`get(foo,0)=5`,
这会导致一个错误。
TODO:添加有关l值行为的更多信息。
### `匹配运算符~`
此运算符应理解为`matches`,`contains`,`is in`或`find me something about something`。
对于字符串,它将右操作数作为正则表达式匹配到左操作数,返回:
-如果不匹配,则返回`null`
-匹配短语(如果未应用分组)
-匹配元素(如果应用了一个组)
-如果应用了多个分组,则列出匹配项
这可用于以更复杂的方式从未分析的nbt中提取信息(使用`get(…)`for
更合适的方法)。对于列表,它检查元素是否在列表中,并返回
该元素的索引,如果找不到此类元素,则为`null`,特别是使用`first(…)`
函数不会返回索引。目前它对数字没有任何特殊的行为-它检查
左操作数相对于上正则表达式的字符串表示中的字符的存在性
右手边。
在Minecraft API中,`entity~feature`部分是`query(entity,feature)`的快捷码,用于不接受
任何额外的参数。
<pre>
[1,2,3] ~ 2 => 1
[1,2,3] ~ 4 => null
‘foobar’ ~ ‘baz’ => null
‘foobar’ ~ ‘.b’ => ‘ob’
‘foobar’ ~ ‘(.)b’ => ‘o’
‘foobar’ ~ ‘((.)b)’ => [‘ob’, ‘o’]
‘foobar’ ~ ‘((.)(b))’ => [‘ob’, ‘o’, ‘b’]
‘foobar’ ~ ‘(?:(.)(?:b))’ => ‘o’
player(‘*’) ~ ‘gnembon’ // null unless player gnembon is logged in (better to use player(‘gnembon’) instead
p ~ ‘sneaking’ // if p is an entity returns whether p is sneaking
</pre>
或者是一个寻找鱿鱼的无效方法的较长的例子
<pre>
entities = entities_area(‘all’,x,y,z,100,10,100);
sid = entities ~ ‘Squid’;
if(sid != null, run(‘execute as ‘+query(get(entities,sid),’id’)+’ run say I am here ‘+query(get(entities,sid),’pos’) ) )
</pre>
或者一个例子,以找出如果一个球员有一个特定的附魔持斧(任何一只手),并获得其水平
(未通过`get(…)“使用正确的NBTs查询支持):
<pre>
global_get_enchantment(p, ench) -> (
$ for([‘main’,’offhand’],
$ holds = query(p, ‘holds’, _);
$ if( holds,
$ [what, count, nbt] = holds;
$ if( what ~ ‘_axe’ && nbt ~ ench,
$ lvl = max(lvl, number(nbt ~ ‘(?<=lvl:)\\d’) )
$ )
$ )
$ );
$ lvl
$);
/script run global_get_enchantment(player(), ‘sharpness’)
</pre>
### `基本算术运算符+-*/`
允许添加两个表达式的结果。如果操作数解析为数字,则结果是算术运算。
对于字符串,从字符串中加或减将导致字符串串联和删除子字符串
从那根绳子上。字符串和数字相乘的结果是将字符串重复N次并得到除法结果
在字符串的第一个第k部分,所以`str*n/n~str`
如果第一个操作数是一个列表,则
结果是一个新的列表,其中所有元素都被另一个操作数逐个修改,或者如果该操作数是一个列表
具有相同的项数-按元素进行加法/减法。这将优先考虑将列表视为值容器
作为向量处理的列表。
使用maps(`{}`或`m()`)进行加法,如果两个操作数都是maps,则会产生一个新的maps,其中两个maps的键都被添加,
将right参数的元素添加到键,left map的元素,或者只是将right值添加为新键
在输出映射中。
示例:
<pre>
2+3 => 5
‘foo’+3+2 => ‘foo32’
‘foo’+(3+2) => ‘foo5’
3+2+’bar’ => ‘5bar’
‘foo’*3 => ‘foofoofoo’
‘foofoofoo’ / 3 => ‘foo’
‘foofoofoo’-‘o’ => ‘fff’
[1,2,3]+1 => [2,3,4]
b = [100,63,100]; b+[10,0,10] => [110,63,110]
{‘a’ -> 1} + {‘b’ -> 2} => {‘a’ -> 1, ‘b’ -> 2}
</pre>
### `仅运算符%^`
只有当两个操作数都是数字时,模和指数(幂)运算符才起作用
<pre>
pi^pi%euler => 1.124….
-9 % 4 => -1
9 % -4 => 0 ¯\_(ツ)_/¯ Java
-3 ^ 2 => 9
-3 ^ pi => // Error
</pre>
### `比较运算符==!=<><=>=`
允许比较两个表达式的结果。对于数字,它考虑的是数字的算术顺序
字符串-按字典顺序排列,空值总是比其他值`少`,列表检查它们的元素-
如果大小不同,则大小很重要,否则,将对每个元素执行成对比较。
与所有这些运算符相同的顺序规则用于`sort`使用的默认排序顺序
功能。所有这些都是正确的:
<pre>
null == null
null != false
0 == false
1 == true
null < 0
null < -1000
1000 < ‘a’
‘bar’ < ‘foo’
3 == 3.0
</pre>
### `逻辑运算符&&||`
这些运算符分别计算操作数上的布尔运算。重要的是如果计算
第二个操作数不是必需的,它不会被计算,这意味着可以将它们用作条件语句。在
case of success返回第一个正操作数(` | `)或最后一个正操作数(`&&`)。
<pre>
true || false => true
null || false => false
false || null => null
null != false || run(‘kill gnembon’) // gnembon survives
null != false && run(‘kill gnembon’) // when cheats not allowed
null != false && run(‘kill gnembon’) // gnembon dies, cheats allowed
</pre>
### `赋值运算符=<>+=`
一组赋值运算符。在LHS上都需要有界变量,`<>`在LHS上需要有界参数
右边也是(有界的,意思是变量)。此外,它们还可以处理列表构造函数
使用所有有界变量,然后作为列表赋值运算符。当在列表上使用`+=`时,它会扩展
元素的列表,并返回列表(old==new)`scarpet`当前不支持删除项目。
可以通过`filter`命令删除项目,并将其重新分配给同一变量。两次行动都会
无论如何都需要重写数组。
<pre>
a = 5 => a == 5
[a,b,c] = [3,4,5] => a==3, b==4, c==5
[minx,maxx] = sort(xi,xj); // minx assumes min(xi, xj) and maxx, max(xi, xj)
[a,b,c,d,e,f] = [range(6)]; [a,b,c] <> [d,e,f]; [a,b,c,d,e,f] => [3,4,5,0,1,2]
a = [1,2,3]; a += 4 => [1,2,3,4]
a = [1,2,3,4]; a = filter(a,_!=2) => [1,3,4]
</pre>
### `一元运算符-+`
需要一个数字,翻转标志。断言它是一个数字的一种方法是使脚本崩溃。gg。
<pre>
-4 => -4
+4 => 4
+’4′ // Error message
</pre>
### `求反运算符 !`
翻转表达式的布尔条件。等价于`bool(expr)==false`
<pre>
!true => false
!false => true
!null => true
!5 => false
!l() => true
!l(null) => false
</pre>
### `解包运算符 …`
将迭代器列表中的元素解压到函数中的一系列参数中,从而生成`fun(…[1,2,3])`
与`fun(1,2,3)`相同。对于映射,它将它们解压到一个键值对列表中。
在函数签名中,它标识vararg参数。
<pre>
fun(a, b, … rest) -> [a, b, rest]; fun(1, 2, 3, 4) => [1, 2, [3, 4]]
</pre>
`…`的效果可以惊人地持久。它通过使用变量和函数调用来保持。
<pre>
fun(a, b, … rest) -> [a, b, … rest]; fun(1, 2, 3, 4) => [1, 2, 3, 4]
args() -> … [1, 2, 3]; sum(a, b, c) -> a+b+c; sum(args()) => 6
a = … [1, 2, 3]; sum(a, b, c) -> a+b+c; sum(a) => 6
</pre>
解包机制可以用于列表和映射压缩,而不仅仅是函数调用。
<pre>
[…range(5), pi, …range(5,-1,-1)] => [0, 1, 2, 3, 4, 3.14159265359, 5, 4, 3, 2, 1, 0]
{ … map(range(5), _ -> _*_ )} => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
{…{1 -> 2, 3 -> 4}, …{5 -> 6, 7 -> 8}} => {1: 2, 3: 4, 5: 6, 7: 8}
</pre>
精细打印:参数列表的解包发生在函数求值之前。
这意味着在某些情况下,例如
当需要表达式(`map(list,expr)`)或函数不应计算某些(most!)它的参数(`if(…)`),
解包无法使用,将被忽略,留下`。。。list`与`list`相同。
不尊重解包机制的函数,一开始就不应该使用它
(即,有一个或非常明确的,非常具体的参数),
因此,建议谨慎(测试前)。其中一些多参数内置函数
`if`,`try`,`sort key`,`system variable get`,`synchronize`,`sleep`,`in dimension`,
所有容器函数(`get`,`has`,`put`,`delete`),
以及所有循环函数(`while`,`loop`,`map`,`filter`,`first`,`all`,`c_for`,`for`和`reduce`)。
#算术运算
##基本算术函数
他们有很多人——他们需要一个数字,然后吐出一个数字,做你希望他们做的事情。
### `fact(n)`
一个数的阶乘,又称n,只是不在`scarpet`里。变大了。。。快。。。
### `sqrt(n)`
平方根。对于其他花哨的词根,请使用`^`,数学和yo noggin。想象一下树上的平方根。。。
### `abs(n)`
绝对值。
### `round(n)`
最接近的整数值。你知道地球也是圆的吗?
### `floor(n)`
仍然不大于`n`的最大整数。在这里插入地板双关语。
### `ceil(n)`
第一个不小于`n`的幸运整数。正如你所料,天花板通常就在地板的正上方。
### `ln(n)`
n的自然对数。当然。
### `ln1p(n)`
n+1的自然对数。非常乐观。
### `log10(n)`
n的十进制对数。它的天花板和地板一样长。
### `log(n)`
n的二元对数。最后,一个合适的,不像前11个。
### `log1p(n)`
n+1的二元对数。也总是积极的。
### `mandelbrot(a,b,极限)`
为集合`a`和`b`计算mandelbrot集合的值。找出甲虫。为什么不。
### `min(arg,…),min(列表),max(arg,…),max(列表)`
假设默认排序顺序,计算提供的参数的最小值或最大值。
如果缺少argmax,只需使用a~max(a),效率稍低,但仍然很有趣。
有趣的位-`min`和`max`不会从参数中删除变量关联,这意味着可以用作
赋值的LHS(明显的情况),或者函数定义中的参数spec(远不那么明显)。
<pre>
a = 1; b = 2; min(a,b) = 3; l(a,b) => [3, 2]
a = 1; b = 2; fun(x, min(a,b)) -> l(a,b); fun(3,5) => [5, 0]
</pre>
完全不知道,后者在实践中如何有用。但既然它编译好了,就可以发货了。
### `relu(n)`
n的线性整流器。0低于0,n高于0。为什么不呢`max(0,n)`道德影响较小。
## 三角函数/几何函数
### `sin(x)`
### `cos(x)`
### `tan(x)`
### `asin(x)`
### `acos(x)`
### `atan(x)`
### `atan2(x,y)`
### `sinh(x)`
### `cosh(x)`
### `tanh(x)`
### `sec(x)`
### `csc(x)`
### `sech(x)`
### `csch(x)`
### `cot(x)`
### `acot(x)`
### `coth(x)`
### `asinh(x)`
### `acosh(x)`
### `atanh(x)`
### `rad(deg)`
### `deg(rad)`
随心所欲
# 系统功能
## 类型转换函数
### `copy(expr)`
返回表达式的深度副本。可用于复制可变对象,如地图和列表
### `type(expr)`
返回指示表达式类型的字符串值。可能的结果
是`null`,`number`,`string`,`list`,`map`,`iterator`,`function`,`task`,
以及`block`,`entity`,`nbt`,`text`等与地雷相关的概念。
### `bool(expr)`
返回表达式的布尔上下文。
Bool还将字符串值解释为boolean值,这与其他方法不同
可以使用布尔上下文的位置。这可用于API函数向其返回字符串值的地方
表示二进制值。
bool(pi) => true
bool(false) => false
bool(”) => false
bool(l()) => false
bool(l(”)) => true
bool(‘foo’) => true
bool(‘false’) => false
bool(‘nulL’) => false
if(‘false’,1,0) => true
</pre>
### `number(expr)`
返回表达式的数字上下文。可用于从字符串或其他类型读取数字
<pre>
number(null) => 0
number(false) => 0
number(true) => 1
number(”) => null
number(‘3.14’) => 3.14
number(l()) => 0
number(l(”)) => 1
number(‘foo’) => null
number(‘3bar’) => null
number(‘2’)+number(‘2’) => 4
</pre>
### `str(expr)`,`str(expr, params? … )`, `str(expr, param_list)`
如果用一个参数调用,则返回该值的字符串表示形式。
否则,返回表示表达式的格式化字符串。格式化的参数可以提供为
每个连续的参数,或作为一个列表,然后将是唯一的额外参数。格式化一个列表参数
,可以使用`str(list)`或`str(`foo%s`,l(list))`。
接受`String.format`接受的格式样式。
支持的类型(使用“%<?>“语法):
* `d`, `o`, `x`: integers, octal, hex
* `a`, `e`, `f`, `g`: floats
* `b`: booleans
* `s`: strings
* `%%`: ‘%’ character
<pre>
str(null) => ‘null’
str(false) => ‘false’
str(”) => ”
str(‘3.14’) => ‘3.14’
str([]) => ‘[]’
str([”]) => ‘[]’
str(‘foo’) => ‘foo’
str(‘3bar’) => ‘3bar’
str(2)+str(2) => ’22’
str(‘pi: %.2f’,pi) => ‘pi: 3.14’
str(‘player at: %d %d %d’,pos(player())) => ‘player at: 567, -2423, 124’
</pre>
* * *
## 线程和并行执行
Scarpet允许与主脚本执行线程并行运行执行线程。在Minecraft中,应用程序
在主服务器线程上执行。既然雷艇本身就不是线程安全的,那就不是了
有利于并行执行,以便更快地访问世界资源。`getBlockState`和`setBlockState`
不是线程安全的,需要将执行停在服务器线程上,这些请求可以在服务器线程中执行
两次滴答之间的停止滴答的时间,并不需要全部50毫秒。但是并行运行也有好处,
像精细的时间控制不依赖滴答的时钟,或运行的东西相互独立。你还可以跑
您的操作是逐点进行的,或者使用`game tick()`API函数控制执行
(讨厌的解决方案),或者使用 `schedule()` 函数调度tick(首选解决方案),但是线程提供了更多的控制
在时间上不影响主博弈,是解决并行问题的唯一方法
(参见[scarpet camera](/src/main/resources/assets/carpet/scripts/camera.sc))。
由于游戏的限制,线程也有一些限制。你不能因为
实例 `join_task()` 完全来自主脚本和服务器线程,因为任何对Minecraft的使用都是特定的
需要任何世界访问的函数,将需要在主线程上驻车并连接以获得世界访问,
这意味着对该任务调用join将不可避免地导致典型的死锁。你仍然可以加入任务
因为在这种情况下,死锁的唯一可能来自
糟糕的代码,而不是内部世界访问行为。有些事情很棘手,比如玩家或实体操纵,可能是
有效地并行化。
如果应用程序正在关闭,则通过`task`创建新任务将不会成功。相反,新任务将什么也不做而返回
`null`,因此大多数线程化应用程序应该能够自然地处理关闭的应用程序。请记住,如果您依赖于任务返回值,
不管在这些情况下发生什么,它们都将返回`null`。当应用程序处理` on close()`事件时,新任务将无法执行
此时无法提交,但当前任务不会终止。应用程序可以利用这个机会优雅地关闭它们的任务。
无论应用程序是否处理` on close()`事件,或对其中的任务执行任何操作,所有任务都将异常终止
在接下来的1.5秒内。
### `task(function, … args)`, `task_thread(executor, function, … args)`
创建并运行并行任务,将句柄返回给任务对象。任务将返回
函数,或者在任务仍在进行时立即返回`null`,因此获取
任务对象是非阻塞的。函数可以是函数值,函数lambda或现有函数的名称
定义的函数。如果函数需要参数来调用,则应在函数之后提供参数
名称或值“task thread`中的executor`identifier`将任务放入由该值标识的特定队列中。
默认线程值是`null`线程。对于任何执行者,并行任务的数量没有限制,
因此,使用不同的队列仅用于同步目的。
<pre>
task( _() -> print(‘Hello Other World’) ) => Runs print command on a separate thread
foo(a, b) -> print(a+b); task(‘foo’,2,2) => Uses existing function definition to start a task
task_thread(‘temp’, ‘foo’,3,5); => runs function foo with a different thread executor, identified as ‘temp’
a = 3; task_thread(‘temp’, _(outer(a), b) -> foo(a,b), 5)
=> Another example of running the same thing passing arguments using closure over anonymous function as well as passing a parameter.
</pre>
如果您想基于模块中未定义的函数创建任务,请阅读上的提示
`将函数引用传递给应用程序的其他模块`部分。
### `sleep()` `sleep(timeout)`, `sleep(timeout, close_expr)`
暂停线程(或游戏本身,如果不是作为任务的一部分运行)的执行 `expr` 毫秒。
它检查中断的执行,在这种情况下退出线程(或者整个程序,如果不是在线程上运行的话)以防应用程序
正在停止/删除。如果指定了关闭表达式,则在触发关闭信号时执行该表达式。
如果在主线程上运行(即不作为任务运行),则只有在整个游戏关闭时才能调用close表达式,因此只能调用close
对线程有意义。对于常规程序,请使用` on close()`处理程序。
由于`close_expr`是在应用程序关闭启动后执行的,因此您将无法在该块中创建新任务。线程
应该定期调用`sleep`,以确保所有应用程序任务在应用程序关闭时或之后立即完成,但应用程序引擎
不会强制删除正在运行的任务,因此任务本身需要正确响应关闭请求。
<pre>
sleep(50) # wait for 50 milliseconds
sleep(1000, print(‘Interrupted’)) # waits for 1 second, outputs a message when thread is shut down.
</pre>
### `task_count(executor?)`
如果未提供参数,则返回此时使用scarpet并行执行的任务总数
穿线系统。如果提供了执行器,则返回该提供程序的活动任务数。使用 `task_count(null)`
仅获取默认执行器的任务计数。
### `task_value(task)`
返回任务返回值,如果任务尚未完成,则返回 `null`。这是一个非阻塞操作。与 `join task` 不同,
可以在任何时候调用任何任务