挑战
您的挑战是为一种类似Lisp的语言设计一个解释器,此后将被创造出来:GLisp。GLisp的程序代码将包含任意数量的由方括号表示的嵌套表达式,格式如下:
(func arg1 arg2 ...)
注意,解释器必须在方括号,函数和参数之前和之后允许多余的空格字符。
种类
您将实现四种类型,整数,列表,布尔值和函数。可以使用自己的语法将整数和布尔值显式插入源代码中。您的解释器必须假设一系列数字字符表示一个整数(您不必实现显式插入负整数的语法)。您的解释器还必须假定true
和false
被指定为布尔值。用户无法明确定义函数,它们将始终返回单个值(任何长度的列表都计为单个值)。
功能
需要实现以下功能,格式为Function,Arity。如果Arity n
以加号开头,则表示一个n
或多个参数。除非另有说明,否则您可以假定赋予函数的所有参数都属于同一类型。您还可以假设如果没有为certian类型指定任何行为,则可以假定该函数的任何参数都不会属于该类型。下图将引用参数:
(func argument1 argument2 ... argumentn)
+,2+
- 如果所有参数均为Integer类型,则必须返回参数之和
- 如果所有参数均为List类型,则必须按升序(
arg1+arg2+ ...
)返回参数的串联 - 如果所有参数的类型均为Boolean,则必须返回逻辑上所有参数序列
(+ 1 2 3 4 5) -> 15
(+ (list 1 2) (list 3 4)) -> (list 1 2 3 4)
(+ true true true) -> true
-,2+
- 如果所有参数均为Integer类型,则必须返回参数的差值(
arg1-arg2- ...
) - 如果所有参数的类型均为Boolean,则必须返回逻辑逻辑上的任意参数序列
(- 8 4 3) -> 1
(- 0 123) -> -123
(- true false false true false) -> true
- 如果所有参数均为Integer类型,则必须返回参数的差值(
*,2+
- 如果所有参数均为Integer类型,则必须返回参数的乘积
- 如果一个参数的类型为List,而另一个参数的类型为Integer(您可以假定这些仅是给定的唯一参数),则必须重复返回包含项的新List。
arg1
arg2
(* 1 2 3 4 5) -> 120
(* (list 1 2 3) 2) -> (list 1 2 3 1 2 3)
/,2+
- 如果所有参数均为Integer类型,则必须返回参数(
arg/arg2/ ...
)的商(您可以假定除法是顺序进行的,并且每一步的小数部分都将被截断) - 如果一个参数的类型为List,另一个参数的类型为Function,则必须在映射到每个值之后返回结果List
arg2
(/ 100 10 3) -> 3
(/ (list 1 2 3) inc) -> (list 2 3 4)
- 如果所有参数均为Integer类型,则必须返回参数(
%,2
- 如果所有参数均为类型 Integer,则必须返回参数的模数
(% 4 2) -> 0
=,2+
- 如果双方的所有参数的类型和值是一样的,你必须返回true。否则,返回false。
(= 0 0 0) -> true
(= 0 false (list)) -> false
清单,0 +
- 您必须返回所有参数的列表,无论类型如何。如果未提供任何参数,则必须返回一个空列表
(list 3 4 (list 5)) -> (list 3 4 (list 5))
公司 1
- 如果参数为整数类型,则必须返回以1递增的Integer
- 如果参数的类型为List,则必须将List沿顺时针方向旋转一圈后返回
(inc 1) -> 2
(inc (list 1 2 3)) -> (list 3 1 2)
十二月 1
- 如果参数为Integer类型,则必须返回减1 的Integer。
- 如果参数为List类型,则必须将逆时针旋转的List返回一圈
(dec 1) -> 0
(dec (list 1 2 3)) -> (list 2 3 1)
如果,3
- 如果给定三个任意类型的参数:如果
arg1
true为true,则返回arg2
,否则返回arg3
(if (not (list 1)) 8 false) -> false
- 如果给定三个任意类型的参数:如果
不是 1
- 如果给定任何类型的参数,则如果true
arg1
为False,则返回true
,否则返回false
。 (not (list)) -> true
- 如果给定任何类型的参数,则如果true
伦 1
- 如果给出类型为List的参数,则返回的长度
arg1
(len (list 4 2 true (list 3) (list))) -> 5
- 如果给出类型为List的参数,则返回的长度
真值表:
0, (list), false -> false
,其中(list)
表示空列表。其他一切都是true
。
您的解释器可以是从stdin或文件中读取源输入的完整程序,也可以是将源作为字符串并返回输出值的函数。
如果选择前者,输出为整数是简单的数字,用于布尔是true
或false
,和用于列表是一个空格分隔包含在括号(例如值的序列(1 2 3 4 (5 6 7))
表示(list 1 2 3 4 (list 5 6 7))
)。
如果选择后者,则必须以实现语言的相应类型返回该值,或者如果不存在类似类型,则返回一个自定义类型。如果语言没有列表类型,则列表可以作为数组或向量返回;布尔应以该语言的布尔类型返回;如果语言不支持布尔型,则返回自定义类型。
测试用例
(list 1 2 3 (list 4 5 true)) -> (1 2 3 (4 5 true))
(/ 4000 (+ 1 2 3 4 (* 5 8))) -> 80
(+ (not (- (len (list 5 6 7)) (/ 10 3))) true) -> true
(if ( len (list ) ) 4 (if (+ (= 8 8 8) (not (list 4))) 8 5)) -> 5
澄清说明
- 您的解释器可能会以您选择的任何方式处理无效输入,但不得引发异常(尽管可能会输出错误消息并顺利退出)
- 函数将始终从左到右评估参数
- 无效输入是指语法上不正确的任何输入。这包括但不限于括号不匹配,被零除和部分应用的功能(除非获得奖金)
- 对于
=
,如果任何值不同或任何类型不同,则返回false
奖金
- 如果支持部分应用的功能,则得分* 0.8。例如,
((+ 2) 3)
与相同(+ 2 3)
,但允许使用(/ (list 1 2 3) (+ 2))
。如果函数接收的参数少于其最小数量,则可以假定该函数已部分应用 - 如果不评估适用的参数(
if
除非将要返回的参数),则得分* 0.85
这是代码高尔夫球,因此字节数最少的解释器获胜!
(+ 3 (if false 5))
?一般来说,什么都不是?您未指定要重调的任何单元类型
(+ bool bool...)
逻辑与和(- bool bool...)
逻辑或?标准的环符号将+
用于OR和*
AND。2.“无效输入”是否旨在涵盖(/ 2 0)
语法上正确的情况?3.对于=
,如果值不完全相同,是否应该返回false
?4.的定义not
似乎是倒退的。5.什么是代币?您说的是解释器必须处理额外的空格,但您没有说它可以依靠什么空格。对于类似这样的复杂问题,您确实应该使用沙盒,以便可以检查规格。
((+ 2 3) 4)
等于9
还是错误?值得注意的是,对于var-arg函数,尚不清楚何时应考虑将应用程序局部化。它变得更加混乱((if true (+ 2 3) (- 5)) 4)
(if (not (array 1)) 8 false) -> false
?