TXR Lisp-来自Lisp语言家族的一种创新的原创方言

2020-09-12 17:18:09

TXR Lisp是从Lisp语言发展而来的一种创新的原创方言。它不是Common Lisp、Scheme或任何现有方言的实现。

TXR Lisp的目标之一是消除Lisp编程中的冗长,这样做不会与Lisp的思想冲突。这意味着使程序简洁的主要手段是类似的设备,而不是语法上的糖块。然而,当糖不破坏周围的语法时,它们也会被使用。

TXR Lisp的另一个目标是作为一个平台来体验Lisp范例中的进步,并将高级功能的正确组合以及针对旧问题的创新新解决方案结合在一起,将这些整合成一个符合人体工程学的整体,现在就可以应用到实际的实际任务中。

TXR Lisp支持函数式编程,但它不是一种函数式语言。TXR项目有意识地拒绝纯粹的功能性意识形态。TXR Lisp通过提供以下功能支持具有高阶函数的编程。

TXR Lisp直接支持命令式编程。它具有可变变量和可变数据结构,如列表、向量、字符串和结构。它具有循环、异常处理和非本地出口等控制结构。

TXRLisp经过严格评估。在函数调用发生之前,函数参数表达式按从左到右的顺序进行计算。特殊运算符和宏以可预测的顺序计算形式。对具有可视效果(如I/O)的操作进行排序很容易,就像在任何主流命令式语言中一样。然而,TXR Lisp通过以下几个特性支持懒惰评估:

惰性实例化OOP结构;允许一步创建由对象组成的无限惰性结构、对象和相互引用的对象集群。

TXR Lisp';在严格的语言中间为显式惰性构造的结构提供了惰性计算的大部分好处,而没有诸如性能差、语义混乱和副作用协调笨拙之类的缺点,这些缺点困扰着惰性计算的函数语言。

与主流的Lisp方言不同,TXR Lisp允许将传统的列表操作(如car、cdr和mapcart)应用于向量和字符串,这非常有表现力和实用性。

在设计Lisp方言时,一个典型的两难境地是将其设置为Lisp-1还是Lisp-2。也就是说,函数和变量绑定应该在一个名称空间中还是在不同的名称空间中?TXR LISP在这一领域进行了创新,推出了一种集成了这两种风格的新解决方案。底层基础结构是Lisp-2:全局和词法环境具有函数和变量名称空间。然而,Lisp-1风格的参数计算(两个名称空间显然合并为一个)的形式是使用方括号而不是圆括号编写的。这个特性被深度集成到语言中;如果不在实现级别上工作,或者使用代码遍历程序转换整个顶级表单,或者使其变得不完整,它就不能用Lisp-2方言实现到同一级别。即使宏扩展器也知道这一特性:当对某个词法函数的引用作为Lisp-1样式参数出现时,该函数会在外部作用域中隐藏一个符号宏,由于符号宏会被考虑在变量名称空间中,因此在Lisp-2形式中不会被隐藏。

在TXR Lisp中使用函数参数(高阶函数)进行编程不会像funcall和#';那样有干扰。funcall函数存在,并命名为call,函数运算符称为FUN;但这些都是很少见过的。缺少Common Lisp#';(散列引号)表示法。TXRLisp语言中的lambda运算符直接工作;它不是一个需要扩展的宏(Fun(lambda...))。目前为止,TXR Lisp保留了Lisp-2的优势,例如它对宏编程和引用卫生的自然视图。(=。

顺便说一句,TXR Lisp中的方括号形式提供了Lisp-1而不是Lisp-1方言本身。Lisp-1方言的支持者喜欢说,表单的每个位置都以相同的方式计算,这比特殊对待运算符的Lisp-2更一致。不幸的是,这是个谎言,因为任何有价值的Lisp-1方言都有宏。必须在宏名空间中考虑任何有价值的Lisp-1方言中aform的最左边位置。相比之下,TXR Lisp的方括号表单不能是宏表单。在形式[a b c]中,第一个符号a必须解析为函数或可用作函数的对象。它不能是宏(而不是简单地用另一种形式替换的符号宏)。因此,具有讽刺意味的是,Lisp-1倡导的声音片段在TXRLisp中是正确的:方括号形式的论点都是以相同的方式计算的,句号。

第一次遇到主要Lisp方言之一的程序员通常会抱怨对数组的笨拙支持。TXR Lisp注意到了这些抱怨。TXR';的方形括号表单提供数组索引和范围引用。

索引工作很自然,因为序列(列表、向量和数组)以及散列被认为是将索引映射到元素的函数。例如,形式(mapcar";abc";#(2 0 1))产生矢量#(#\c#\a#\b),因为字符串";abc";是将索引0、1和2映射到字符对象#\a、#\b和#\c的函数。(还要注意,向量是用mapcar处理的,这就是出现的类型是向量的原因)。因此,方括号Lisp-1表示法提供了数组索引。形式[";abc";1]表示";调用";abc";字符串作为函数,并向其传递参数1";。其效果是检索到字符#\bis。这对列表和向量的工作方式相同。对于哈希表,执行哈希查找。如果h是哈希表,i和k是键,则[h k]执行查找。此外,[h k v]执行查找,例如,如果找不到k,则替换v。

使用点范围表示法支持范围索引。例如实例[a2..5]表示从元素[a2]开始直到并包括[a4]的切片,不包括[a5]。如果符号t用作上端点,则它表示超出最后一个的元素;换句话说,切片延伸到末尾。冒号:也可以用在任何一端,以表示从开始";或";到结束";的";。.以下所有形式都表示a的切片,其中包括a:a:..:],[a0..:],[a 0..t],[a:..t]。支持所有负索引,因此-1表示最后一个元素。表达式[a 0..-1]计算不包括最后一个元素的a的切片。点符号是语法糖,表示Range对象的构造:a..bis已转换。S解析器到(rcons a,b),这是对构建Range对象的rcons函数的调用。

元素索引表和范围索引表都支持赋值和删除(如果类似数组的对象存储在可赋值的表中

(让((a";Archibald&34;)(b";Spooner&34;))(交换[a2.。4][b 0..。2])(列表a b))->;(";arspirbald&34;";chooner";)。

请注意,尽管在本例中交换的范围碰巧长度相等,但这不是一个约束。

在编程语言中,将值直接内插到字符串中是相当方便的。使用它们可以生成简洁、富有表现力的字符串构造代码。主流的Lisp方言在这方面错失良机。TXR Lisp设计的字符串插值比大多数脚本语言都要好。

插入的字符串文字在TXR Lisp中称为准文字,并由反引号而不是双引号分隔。TXR Lisp避免了只支持内插的一种字符串的错误设计。需要字符串,它们是真正的文字。

在反引号字符串中,@字符表示表达式的值的插入。后面紧跟表达式,或用大括号括起来的表达式。大括号符号解决了某些产生的歧义问题,还允许表达用于表示字段宽度、左对齐或右对齐的修饰符和用于合并列表元素的分隔符字符串。示例:

(defvarl str";abc";)(defvarl word';#";)(prinl`@str-@str`)(prinl`@{str 10}-@{str-10}`)(prinl`word&@{word";,";-40}`)。

准文字和常规字符串文字都可以以#作为前缀,表示单词列表。在上面的示例中,#";How Now棕色奶牛&34;表示列表结构(";How";";";";棕色";";奶牛";)。前面加引号表示引用列表';(";HOW";";NOW";";Brown";";COW";)。省略引号是必要的,因为单词列表可以嵌入到未计算的结构中。但是,准文字是用于求值的结构,因此表达式#‘How now Brown cos’的求值结果为列表(";How";";";";";";";cow";),不需要引号。准文字语法生成的代码在计算时会构造隐含的字符串或字符串列表,而普通文字将字符串或字符串列表表示为程序语法。

TXR Lisp没有类似于Common Lisp的CLOS的对象系统。相反,TXR的结构组成了一个简单的对象系统,具有单一分派和多重继承的特点。

在TXR Lisp中避免使用术语类,而是使用具有面向对象特性的结构(Struct)。结构类型必须使用defstruct宏或它使用的底层API显式定义。结构既有实例槽又有静态槽。在继承中,静态槽可以用实例槽覆盖,反之亦然。方法表示为存储在静态槽中的函数值,因此方法属于结构。通过调度存储在o中名为m的槽中的函数来分派名为On的对象实例o的方法。该函数接收对象作为其最左边的参数,后跟剩余的方法参数。可以将新的静态插槽添加到现有类型。此外,具有继承的静态槽的atype可能会打破这种关系,并获得它自己的静态槽的非继承实例。这是defstruct之外的方法定义和重定义的基础。

TXR Lisp以点符号为特色,用于引用结构槽,包括方法槽。例如SIM.START-TIME(设置42)意味着检索SIMSTRUCTURE的时隙开始时间,然后在该开始时间调用SET方法。该表示法是Lisp语法(qref sim start-time(设置42))的语法糖。QrefSymbol有一个宏绑定;该宏将抽象语法编译成它所表示的槽引用和函数调用。

假设我们有一个对象列表,并且我们想要调用Seton它们各自的开始时间成员以将它们的时间重置为零:

这里,点符号以一个前导点开始。记号的这个变体不对应于qref,而对应于uref(未绑定引用):(uref start-time(设置42))。这个uref表单编译成一个更高阶的函数,它接受一个对象作为参数。该函数引用对象的开始时隙,并对其调用setmethod。

对象有构造时调用的方法,也有终结器。当垃圾回收器检测到其终结器尚未调用的不可达对象时,此时将调用终结器。如果对象的终结器在构造过程中发生异常,也会调用该对象的终结器,也可以在对象的生存期结束之前通过call-finalizer函数显式调用该对象的终结器。WITH-OBJECTS宏实例化词法作用域中的对象,并在它们的作用域结束时调用它们的终结器,从而使C++语言中的习惯用法的某些方面可以在TXR Lisp中使用。