如何从命令行格式化常见的 lisp 代码(包括换行符)?

互联网 行业动态 更新时间:2024-06-13 00:19:06

ign*_*ens 7

[这应该是一个评论,但它太长了。]

这介于困难和不可能之间。考虑下面的表格,这里用一条长线给出:

(with-collectors (odd even) (iterate next ((i 0)) (when (< i 100) (if (evenp i) (even i) (odd i)) (next (1+ i)))))

这应该如何缩进?好吧,这是一个完全支持 lisp 的编辑器可能会如何缩进它:

(with-collectors (odd even)
                 (iterate next ((i 0))
                          (when (< i 100) 
                            (if (evenp i)
                                (even i)
                              (odd i))
                            (next (1+ i)))))

那是……大错特错。以下是同一编辑器稍后将如何缩进它:

(with-collectors (odd even)
  (iterate next ((i 0))
    (when (< i 100) 
      (if (evenp i)
          (even i)
        (odd i))
      (next (1+ i)))))

这次它做对了。

发生了什么变化?好吧,改变的是语言:特别是第二个示例中的语言已经扩展为包括with-collectors编辑器现在知道如何处理的iterate表单以及它也可以理解的表单。

所以这似乎是一个模糊的点,但事实并非如此。因为 Lisp 的全部观点(可以说)是,为了解决问题,您可以逐步无缝地将语言从您开始使用的基础语言扩展到您想要用来解决问题的语言。

这意味着许多 Lisp 程序由一系列对该语言的扩展组成,然后是用这种新的扩展语言编写的程序,在其中解决了问题。Lisp 是一种面向语言的编程语言

意味着知道如何缩进 Lisp 程序的唯一真正可靠的方法是询问该程序。在上面的示例中,最初系统认为这with-collectors是一个函数,并像那样缩进它。后来,当它知道定义时,它意识到它是一个let-style 结构并正确缩进它。同样对于iterate

这一切意味着一个独立的工具确实没有希望很好地缩进一个实质性的 Lisp 程序,因为要做到这一点,它需要比没有程序的情况下更多地了解程序。当然,这就是为什么 Lisp 鼓励“驻留”开发环境,将正在开发的程序加载到开发环境中,而不是“分离”的开发环境或多或少与正在开发的程序完全分离。 . 通过解析程序中的定义并找出扩展语言的定义,一个独立的工具可能会获得大部分的成功。但要做到这一点,再一次,需要你成为程序。

作为一种面向语言的编程语言带来了显着的好处,但也带来了成本,不幸的是,这就是其中之一。


如果您的任务非常有限,并且如果您真的想在一行上表达一些大的表达(因此,可能没有评论),那么下面将尝试执行此操作。你需要把它包装成一个程序。

买者自负。该代码肯定是不安全的,并且可以根据其输入执行任意代码。除非您确定您输入的输入是安全的,否则不要使用。所以,事实上,不要使用它。

;;;; Note horrid code, This is *certainly* unsafe
;;;
;;; This uses EVAL which I think is necessary here, but is what makes
;;; it unsafe.
;;;

(in-package :cl-user)

(eval-when (:pile-toplevel :load-toplevel :execute)
  (warn "UNSAFE CODE, USE AT YOUR OWN RISK."))

(defvar *tlf-handlers* (make-hash-table))

(defmacro define-tlf-handler (name ds-arglist &body forms)
  (let ((formn (make-symbol "FORM")))
    `(progn
       (setf (gethash ',name *tlf-handlers*)
             (lambda (,formn)
               (destructuring-bind ,ds-arglist (rest ,formn)
                 ,@forms)))
       ',name)))

(define-tlf-handler in-package (package)
  (let ((p (find-package package)))
    (if p
        (progn
          (format *debug-io* "~&Setting package ~S~%" package)
          (setf *package* p))
      (warn "no package ~S" package))))

(define-tlf-handler defpackage (package &body clauses)
  (format *debug-io* "~&Defining package ~S~%" package)
  (eval `(defpackage ,package ,@clauses)))

(define-tlf-handler defmacro (name arglist &body forms)
  (format *debug-io* "~&Defining macro ~S~%" name)
  (eval `(defmacro ,name ,arglist ,@forms)))

(define-tlf-handler eval-when (times &body forms)
  (declare (ignore times forms))
  (warn "Failing to handle eval-when"))

(define-condition pps-reader-error (reader-error simple-error)
  ())

(defparameter *pps-readtable* (copy-readtable nil))

(set-dispatch-macro-character
 #\# #\+
 (lambda (s c n)
   (declare (ignore c n))
   (error 'pps-reader-error
          :stream s
          :format-control "Can't handle #+"))
  *pps-readtable*)

(set-dispatch-macro-character
 #\# #\-
 (lambda (s c n)
   (declare (ignore c n))
   (error 'pps-reader-error
          :stream s
          :format-control "Can't handle #-"))
  *pps-readtable*)

(defun pp-stream (s &optional (to *standard-output*))
  (with-standard-io-syntax              ;note binds *package*
    (let ((*readtable* *pps-readtable*)
          (*read-eval* nil)
          (*print-case* :downcase))
      (do ((form (read s nil s) (read s nil s)))
          ((eq form s) (values))
        (format to "~&")
        (pprint form to)
        (when (and (consp form) (symbolp (car form)))
          (let ((handler (gethash (car form) *tlf-handlers*)))
            (when handler (funcall handler form))))))))

(defun pp-file (f &optional (to *standard-output*))
  (with-open-file (in f)
    (pp-stream in to)))

更多推荐

命令行,常见,代码,换行符,lisp

本文发布于:2023-04-20 20:48:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/hyzx/edb91d6347ca569220ace2661c899577.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:命令行   常见   代码   换行符   lisp

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!