写一个班次翻译
编辑:你们中有些人怀疑,官方解释器中有一个错误:组成顺序.颠倒了。我有两种版本的解释器,在这里使用了错误的一种。这些示例也是针对此错误版本编写的。我已经修复了存储库中的解释器以及以下示例。的描述>也有点模棱两可,所以我已经解决了。而且,为此花了很长时间的道歉,我陷入了一些现实生活中。 EDIT2:我的解释器在实现中存在一个错误,该错误.反映在示例中(它们依赖于未定义的行为)。现在,此问题已解决。 介绍 Shift是我几年前制作的一种深奥的函数式编程语言,但今天发布了。它基于堆栈,但是像Haskell一样具有自动监视功能。 规格 Shift中有两种数据类型: 功能,具有任意的正元数(输入次数),并且其返回的输出的列表。例如,一个重复其唯一输入的函数具有arity 1,而交换其两个输入的函数具有arity 2。 空格完全相同,除了没有功能外没有其他目的。 Shift程序包含零个或多个命令,每个命令都是一个ASCII字符。共有8条命令: !(应用)弹出的功能f和值x从堆栈,并适用f于x。如果f为1,则将列表f(x)添加到堆栈的最前面。如果具有arity n > 1,则将一个新的(n-1)-ary函数g推入堆栈。它接受输入并返回。x1,x2,...,xn-1f(x,x1,x2,...,xn-1) ?(空白)将空白推入堆栈。 +(clone)将复制其输入的一元函数压入堆栈:任何值x都映射到[x,x]。 >(shift)将接受n-ary函数的一元函数压入堆栈f,并返回(n+1)-ary函数g,该函数忽略其第一个参数x,调用f其余参数,并x在结果前加钉。例如,shift(clone)是一个二进制函数,它接受输入a,b并返回[a,b,b]。 /(fork)将接受三个输入的三元函数压入堆栈a,b,c,[b]如果a为空白,[c]则返回,否则返回。 $(呼叫)推到堆栈弹出的功能的二元函数f和一个值x,并适用f于x完全一样!一样。 .(chain)将一个二进制函数压入堆栈,该函数会弹出两个函数f和g,并返回它们的组成:h具有与ar相同的Arity 的函数,该函数f通常接受其输入f,然后将它们应用于它们,然后完全应用于g结果(调用它的次数取决于其Arity的规定),而输出中的未使用项f保留在的结果中h。例如,假设f的是,克隆其第二个参数,和一个二进制函数g是呼叫。如果堆栈包含[f,g,a,b,c]并且我们包含.!!,那么它包含[chain(f,g),a,b,c]; 如果我们做!!下一个,然后f首次应用于a,b,产生[a,b,b],则将g其应用于该元素的前两个元素,因为其Arity为2,产生[a(b),b],堆栈最终为[a(b),b,c]。 @(比如)推送一元函数,该函数仅返回其输入,并0在其为空白以及1为函数的情况下进行打印。 请注意,除!简单地将一个值压入堆栈外,所有命令均无法执行输入,而输出任何内容的唯一方法是use @。通过逐一评估命令,在调用“ say”时打印0s或1s并退出来解释程序。此处未描述的任何行为(应用空格,应用长度为0或1的堆栈,在空格上调用“ chain”等)都是未定义的:解释器可能崩溃,无提示失败,要求输入或执行任何操作。 任务 您的任务是为Shift编写解释器。它应该从STDIN,命令行或函数参数中获取要解释的Shift程序,然后打印到STDOUT或返回0s和1s 的结果(可能是无限的)输出。如果编写函数,则必须能够以某种方式访问无限长的输出(Python中的生成器,Haskell中的惰性列表等)。另外,您也可以输入另一个数字n,n如果长度大于,则返回至少一个字符n。 最低字节数获胜,并且不允许出现标准漏洞。 测试用例 此Shift程序打印01: ?@!@@! 从左侧开始:推一个空格,按下say,然后将say应用于该空格。这输出0。然后,将发言权推两次,然后将第二个发言权应用于第一个发言权。这输出1。 该程序永远循环,不产生任何输出: $+.!!+!! 推动call和clone,然后对其应用链(!由于chain是二进制函数,我们需要两个s )。现在,堆栈包含一个函数,该函数接受一个参数,将其复制,然后在第二个参数上调用第一个副本。使用+!!,我们复制此函数并对其进行调用。 该程序打印0010: ?@$.++>!.!!.!!.!!!!+?/!!!@!@>!!! 推空白并说。然后,编写一个二进制函数,该函数复制其第二个参数b,然后复制第一个参数a并将其与自身组合,然后将该合成应用于的副本b,返回[a(a(b)),b]。其应用到说和空白,然后申请比如说剩余堆栈上的两个元素。 打印此程序0。对于!!!您追加的每个内容,它都会打印出一个额外的0。 ?@+$>!>!+>!///!!>!>!.!!.!!.!!+!!!! 推空白并说。然后,组成一个三元函数,将其f,g,x作为输入并返回[f,f,g,g(x)]。克隆该函数,并将其应用于自身(例如)和空白。该应用程序不会更改堆栈,因此我们可以根据需要多次应用该函数。 此程序将打印无限序列001011011101111...,其中1s 的数量始终增加一: @?/!@>!??/!!>!+.!!.!!.!!.+>!.!!$$$$+$>!>!$>!>!+>!$>!>!>!+>!>!///!!>!>!>!.!!.!!.!!.!!.!!.!!.!!.!!.!!.!!+!!!!! 存储库包含带注释的版本。