在一些lisps (例如elisp、common lisp)中,有一种称为反引号的功能。
它允许在计算或拼接一些元素的同时构造一个列表。例如:
`(1 2 (3 (+ 4 5)))
⇒ (1 2 (3 (+ 4 5))) ; just quoted unevaluated list
`(1 2 (3 ,(+ 4 5)))
⇒ (1 2 (3 9)) ; (+ 4 5) has been evaluated
`(1 2 ,@(list 3 (+ 4 5)))
⇒ (1 2 3 9) ; (3 9) has been spliced into the list我猜,在Haskell中,反引号的一些子集可能如下所示:
[backquote| 1, 2, @$(replicate 2 3), 2 + 2 |]
⇒ [1, 2, 3, 3, 4]我想知道,像这样拼接到列表中是否可能,以及它是否已经实现。
发布于 2019-04-25 21:26:35
评论中的讨论似乎有点脱轨了。无论如何,我对此有不同的看法,所以让我提供一个答案。
我想说的是,Haskell已经有了一个类似于反引号的特性,您可能已经在自己的Haskell编程中广泛地使用了它,而没有意识到这一点。
您已经将Lisp列表与Haskell列表进行了比较,但在Lisp中,S表达式(即“原子对”,尤其是原子符号)是一种灵活且普遍的数据结构,不仅用于表示Lisp代码,而且还用作首选表示法,这至少是任何复杂的结构化数据的首要考虑因素。因此,大多数Lisp程序花费大量时间来生成和操作这些结构,因此S表达式“文字”在Lisp代码中很常见。而且,与尝试使用cons、list、append等函数使用较小的文字和计算片段来构建表达式相比,使用反引号机制编写需要计算一些子表达式的S表达式“几乎字面值”更方便。
与Haskell形成对比-- Haskell列表在Haskell代码中当然很流行,是表示同构序列的首选结构,但它们只提供了S表达式的一小部分灵活性。相反,Haskell中对应的无处不在的数据结构是代数数据类型(ADT)。
嗯,就像Lisp的S表达式一样,Haskell程序花费了大量的时间来生成和操作ADT,而且Haskell还为ADT文本和“几乎文本”提供了一种方便的语法。它们被统一到一个“函数应用”语法中,通过使用构造函数(具有首字母大写字母的标识符或以冒号开头的中缀操作符)和非构造函数(具有首字母小写字母或没有首字母冒号的中缀操作符的标识符)来区分文字和计算部分。当然,对于某些构造函数(列表和元组),还有一些额外的语法。
例如,比较Lisp和Haskell中的以下反引号表达式:
;; Lisp
(setq baz `(node ,id
(node ,(+ id 1) ,left-tree leaf)
(node ,(+ id 2) leaf ,right-tree)))
-- Haskell
baz = Node id (Node (id + 1) left_tree Leaf) (Node (id + 2) Leaf right_tree)在这个“几乎是字面上的”的Haskell版本中,Node和Leaf构造函数表示被引用的部分;left-tree、right-tree和+中缀表达式表示计算的部分,它们在语法上可以通过构造函数和非构造函数的常用规则进行区分。
当然,与此完全不同的是,还有一个模板Haskell机制,它可以在编译时直接操作Haskell代码片段。虽然代码被表示为ADT,原则上可以使用用于其他ADT的相同的“几乎字面”语法来编写,但所讨论的ADT非常繁琐,看起来与底层的Haskell代码完全不同。因此,模板Haskell提供了一种更经典的反引号语法。
https://stackoverflow.com/questions/55767876
复制相似问题