【问题标题】:Pretty-print Lisp using Python使用 Python 漂亮打印 Lisp
【发布时间】:2015-10-24 20:42:17
【问题描述】:

有没有一种方法可以在 Python 中漂亮地打印 Lisp 样式的代码字符串(换句话说,就是一堆平衡的括号和文本),而无需重新发明轮子?

【问题讨论】:

  • 代码字符串是常量还是计算出来的?告诉我们更多关于它的信息......
  • 是解析树,所以是计算出来的
  • 你试过pprint模块吗?文档中的示例似乎表明它可能只是您想要的。 (我假设您已将其作为 S 表达式,如问题中所示,而不是如您的评论所说的那样作为树。)

标签: python lisp pretty-print s-expression


【解决方案1】:

简答

如果可以的话,我认为一种合理的方法是生成 Python 列表或自定义对象而不是字符串,并使用 @saulspatz 建议的 pprint 模块。

长答案

整个问题看起来像XY-problem 的一个实例。为什么?因为您正在使用 Python(为什么不使用 Lisp?)来操作表示生成的 Lisp 样式 代码的 字符串(为什么不使用数据结构?),其中 Lisp-style 被定义为“一堆括号和其中的文本”。 对于“如何打印漂亮?”的问题,我会回复"I wouldn't start from here!"。 除了使用现有的轮子之外,在您的情况下不重新发明轮子的最佳方法是坚持简单的输出格式。

但首先,为什么你需要漂亮的打印?谁会查看生成的代码?

根据您使用的确切 Lisp 方言和代码的预期用途,您可以非常不同地格式化您的代码。例如,考虑文本的换行符、缩进和最大宽度。 Common Lisp pretty-printer 是特别进化的,我怀疑您是否希望拥有相同级别的可配置性。 如果您使用 Lisp,只需调用 pprint 即可解决您的问题,但您使用的是 Python,因此暂时坚持使用最合理的输出,因为漂亮的打印是一罐蠕虫。

如果您的代码是供人类阅读的,请:

  • 不要将右括号放在自己的行中
  • 不要垂直对齐左括号和右括号
  • 不要在左括号之间添加空格

这很丑:

 ( * ( + 3 x )
     (f 
        x
        y
     )
 )

这样更好:

(* (+ 3 x)
   (f x y))

或者简单地说:

(* (+ 3 x) (f x y))

See here了解更多详情。

但在打印之前,您必须解析输入字符串并确保其格式正确。由于您生成表单的方式,也许您确定它格式正确,但我认为打印机应该忽略这一点并且不要做出太多假设。如果您向漂亮的打印机传递一个由 Python 对象而不是字符串表示的 AST,这会更容易,正如 cmets 中所建议的那样。您可以构建数据结构或自定义类并使用 pprint (python) 模块。如上所述,如果您可以更改生成 Lisp 样式代码的方式,这似乎是您的情况。

对于字符串,您应该处理任何可能的输入并拒绝无效的输入。 这意味着检查括号和引号是否平衡(注意转义字符)等。 实际上,您并不需要真正构建用于打印的中间树(尽管它可能对您程序的其他部分有所帮助),因为编写了 Lisp 样式的代码易于嵌套并使用前缀表示法的表单:您可以从左到右扫描输入字符串,并在看到括号时根据需要打印(左括号:递归;右括号,从递归返回)。当您第一次遇到未转义的双引号 " 时,请阅读直到下一个 ",... 这与简单的打印方法相结合,足以满足您的需求。

【讨论】:

    【解决方案2】:

    我认为最简单的方法是使用三引号。如果你说:

    print """
        (((This is some lisp code))) """
    

    它应该工作。 您可以在三引号中以任何您喜欢的方式格式化您的代码,它会以您想要的方式出现。

    祝你好运,编码愉快!

    【讨论】:

    • 感谢您的回复,但问题是关于运行时生成的字符串。
    • @MaxMalysh 当我提出我的答案时,您的 cmets 部分中的讨论尚未发生。我以为你只是在打印格式化的 lisp 代码。
    猜你喜欢
    • 2016-04-26
    • 2014-05-12
    • 1970-01-01
    • 2014-05-18
    • 2020-11-10
    • 2019-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多