# AutoLispBaseFunctionLibrary **Repository Path**: arxref/abfl ## Basic Information - **Project Name**: AutoLispBaseFunctionLibrary - **Description**: 关于AutoCad的AutoLisp/Vlisp的基础通用函数库 - **Primary Language**: Lisp - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 29 - **Created**: 2018-06-06 - **Last Updated**: 2022-11-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # AutoLispBaseFunctionLibrary #项目简介 这是一个关于autocad 的二次开发语言autolisp/vlisp的通用的基础函数库。 ##发起原因 在学习和写autolisp的过程中,学习了很多前辈的代码,好吧我承认是抄。 这些代码零散,需要人整理,虽然网上也有这种整理好的,但是由于发布体制的原因,可维护性及可靠性完全依靠发布者,相当的脆弱。 所以发起这个项目,只是想大家都参与进来,共同建立一个大家能使用,大家能参与的项目,这个项目不依赖任何人的强制想法。 ##代码来源 本项目初始代码来至于我个人整理的一些代码和自己写的代码。 感谢lee mac,高飞鸟,gu_xl,飞诗,熊掌,还有其他的我也记不住名字的人。 能确定代码来源的尽量都加上,没能加上的,如果你反对你的代码加入这个项目,请联系我,我会删除。 ##项目文件结构 * base-utils.lsp —— 基本的函数 * curve-utils.lsp —— 曲线类函数 * entity-utils.lsp —— 图元类函数 * list-utils.lsp —— 列表类函数 * math-utils.lsp —— 数学类函数 * matrix-utils.lsp —— 矩阵类函数 * sel-utils.lsp —— 选择集类函数 * string-utils.lsp —— 字符串类函数 * vla-utils.lsp —— vla对象类函数 * dcl-utils.lsp —— dcl对话框类函数 * file-utils.lsp —— 文件类函数 * excel-utils.lsp —— excel操作函数 * access-utils.lsp —— access数据库操作函数 * doc —— 文档目录 * project —— 项目编译文件的目录 * examples —— 示例文件目录 * readme.md —— 项目介绍及简易编码规范 * license —— 开源许可证声明 ##声明 本项目在有意向的时候,就有人说我是钓鱼,我只想说,滚你妈。 如果为了钓鱼,我不会用了一个月的业余时间来把代码都整理出来,基本上每个都测试过能正常工作。 如果为了钓鱼,我不会把每个函数都写上注释,都生成文档。 如果为了钓鱼,我只想说,愿者上钩,我先上钩了。 最后,请不要以恶意来揣测别人,除了证明你的浅薄,我想不出你还有何价值。 # 简易编码规范 本编码规范参考google common lisp 风格指南结合AutoLisp的特点编写。 ## 通用规则 ### 原则 每一个开发者所写的代码必须让别的开发者容易阅读、理解及改动 ──── 即便最初的开发者已经不在了。(这是 “hit by a truck” 理论。) * 大家的代码看起来要一致。理想上,不应该看到几行代码就认出,啊,这个风格是“vicwjb 写的代码”。 * 追求精准。 * 追求简洁,尽量遵守 KISS 原则(Keep It Simple, Stupid),简单就是美。 * 杀鸡焉用牛刀,用最适当的工具。 * 使用常识。 * 相关代码放在一起。将别人需要理解一部分代码所需的画面跳转减到最低。 ### 优先级 当抉择如何写出一段给定的代码时,依此优先序追求下列性质: * 客户的易用性。 * 可调试性或可测试性。 * 可读性或可理解性。 * 可扩充性或可修改性。 * (运行期 Lisp 代码的)效率。 这些准则大部分都是直观的。 客户的易用性代表系统满足了客户的需求;如:需要处理客户的交易量,正常运作时的需求等等。 针对 Lisp 效率这一点,若是有两个同样复杂的选择,选运行较好的那个。(通常是构造比较少的那个,也就是从堆上配置了较少空间。) 给定两个选择,其中一个比另一个复杂,选择简单的那个,并分析出另一个有更好效能时,才重新审视当初的决定。 然而,避免过早优化。别为了给不常用到的代码提升速度而使复杂度上升。因为长期来说,鲜少运行的代码快不快不是那么重要。 ## 格式化 ### 缩写与拼写 必须在注释里使用正确的拼写,而最重要要拼对的是函数的形参。 当数个正确拼写同时存在时(包括美式及英式英语),而开发者之间尚未有共识存在时,你应该选择较短的拼写。 必须只使用常见与领域相关的缩写,缩写保持一致。可以把受限作用域里的词法变量缩短,来避免符号名称过长。 如果你不确定的话,查字典吧,或是 Google 下来检查拼写。或问问当地的专家。 ### 行长 应该要格式化你的源代码,使单行不超过 100 个字符。 有某些行长限制总比没有好。古老的文字终端机使用 80 栏,但现在允许 100 栏似乎比较好,因为好的风格鼓励你使用具有描述性的变量以及函数名称。 ### 缩排 像配置好的 vlide/其他编辑器 那样缩排你的代码。 (建议使用飞诗Lisp编辑器) 项目里维护一个一致的缩排风格。 审慎的缩排会使代码更容易理解。 ### 垂直空间 垂直空间:顶层级别的形式,一个空行。 应该在顶层级别的形式留一个空行,比如函数定义。在特殊情况下,空行可以省略,简单的、密切相关的、同种类的定义形式,比如一组相关的类型声明,或是常量定义。 空行可以把复杂的函数切分成多个部分。一般来说,你应该要把大函数切成几个小函数,而不是添加垂直空间,让它读起来比较好读。如果你不能够切成小函数,你应该要使用 ;; 注释,说明每个函数的部分各是干嘛的。 ### 水平空间 水平空间:括弧之间不要有空格、tab。 绝对不要在括号或符号的前面或后面加上额外的空白。 ;; 非常差劲 (defun StrUnParse ( Lst Delimiter / return ) ( setq return "" ) ( foreach str Lst ( setq return ( strcat return Delimiter str )) ) ( substr return 2 ) ) ;; 较佳 (defun StrUnParse (Lst Delimiter / return) (setq return "") (foreach str Lst (setq return (strcat return Delimiter str)) ) (substr return 2) ) 形式之间应该只用一个空格。 你不应该在多行连续的中间,使用空格来垂直排列形式。一个例外是当代码不垂直对齐,就看不出你要强调的重要性时。 ;; 差劲 (setq low 1 high 2 sum (+ (* low low) (* high high))) ...) ;; 较佳 (setq low 1 high 2 sum (+ (* low low) (* high high))) ...) 你必须排列嵌套形式,如果他们超过一行的话。 ;; 差劲 (defun munge (a b c) (* (+ a b) c)) ;; 较佳 ``` (defun munge (a b c) (* (+ a b) c)) ``` ## 文档 ### 文档字串 所有函数都应该要使用文档字串,来解释如何使用你的代码。 除非某段代码完全一目了然,不然就上一个文档字串(别名 docstring)。 文档字串生来就是给使用代码的程序员读的。他们可以从函数、类型、类别、变量以及宏取出, 并通过编程工具,如 IDE 来显示。因此,文档字串是给你的 API撰写文档的完美地点。应该描述如何使用代码(包括需要避开的陷阱),而不是代码是如何工作的(以及之后所需的工作),这两个是你该放在注释的东西。 当定义一个顶层及别的函数、类型、类别、变量以及宏时,提供一个文档字串。一般则是在程序语言允许加入文档的地方,添加文档字串。 关于函数,docstring 应该要描述函数的合约: 这个函数干什么, 这个函数的参数表示什么, 这个函数所返回的值, 这个函数可捕捉的状况。 应该在适当的抽象层级上来表达,解释意图,而不仅是解释语法。在文档字串里,将 Lisp 符号的名字转为大写,比如函数参数。 以上应该是用于文档工具生成API文档的文档字串。鉴于AutoLisp貌似没有文档工具支持,因此可以使用分号注释及块注释。 ### 分号注释 你必须使用正确数量的分号来写注释。 注释是给未来维护代码的人的说明。即便你是唯一能够看与接触到代码的人,即便你长生不老或是永远不离职,或是离职之后根本不管的人(并在这种万一的情况下使你的代码自行毁灭),你可能会发现给代码写注释是有帮助的。当然啦,在几个礼拜、月、年之后,回头看看代码时,你会发现当初写这个代码的人,完全与你不是同一个人,则你会感激当初自己有留下注释。 你必须给任何复杂的代码留注释,这样一来下个开发者才可以了解情况。(又来了,“hit by a truck” 理论。) 注释也可以作为指引阅读代码的人的一种方式,这样他们才知道这里有什么。 * 文件头及源文件里大段代码的重要注释,注释应该使用;| |; 块注释。 * 主函数注释应该使用三个分号。 * 在函数里,如果注释出现在行之间(例如内部子函数或重要代码结构),注释应该使用两个分号。 * 如果是一个括号的备注且出现在行的最后,注释应该使用一个分号。你应该使用空格来分离注释与引用的代码,使得注释脱颖而出。你应该试着垂直排列相关的行尾注释。 在分号与注解文字之间,应该留一个空格。 ## 命名 ### 符号准则 使用小写。 所有的符号使用小写。一致地使用小写,除了可读性更高之外,也让查找符号名变得更容易。 注意AutoLisp不区分大小写,而对一个符号调用 vl-symbol-name 时,会返回大写。由于这个转换大小写的特色,当你试着要分辨符号的大小写时,最终只会让你陷入困惑。 在符号的单词之间放连字符。如果你不能很简单的说出标识符的名字,那符号大概命名的很差劲。 连字符必须用 "-",不要用 "/" 、":"或是 "."。除非你有一个无懈可击的理由,以及你的提议取得了来自其他黑客的许可。 ;; 差劲 (setq *default-username* "Ann") (setq *max-widget-cnt* 200) ;; 较佳 (setq *default-user-name* "Ann") (setq *maximum-widget-count* 200) 除非变量的作用域非常小,不要使用过短的名字,像是:`i` 以及 `zq`。 ### 表明目的,而非内容 将变量用目的命名,而不是变量的内容。 应该根据变量所意涵的概念命名,而不是根据概念在机器底层是怎么表示的来命名。 因此,你应该避免嵌入数据结构或结合类型名称,比如将 list 嵌入变量名,除非你正在写一个通用的演算法,适用于任何的列表等等。在这个情况下,变量名有 list是完全没问题的。 举例来说,如果一个变量的值,总是一个 `row`(或是`NIL`),叫它 `row` 或 `first-row` 是很好的,或者是其他相似的名字。严格来说,因为你将细节抽象起来了,剩下的亮点是,它是一个 `row`。 保持一致。如果变量在一个函数里命名成 `row`,且它的值被传给第二个函数,则将其称为 `row` 而不是 `value`。(这是一个实际情况) ### 全局变量 全局变量名应由星号开始,并以星号结束(在这个上下文里,星号又称为耳套「earmuffs」)。 (setq *maximum-search-depth* 100) ### 判断式名称 判断式函数与变量的名字以 "P" 结尾。 你应该将返回布尔值的函数与变量的 结尾以 "P" 或 "-P" 命名, 来表示他们是判断式。 一般来说,你应该使用, 函数名是一个单词时,使用 "P"; 超过一个单词时,使用 "-P"。 为了要统一,你应该遵循上面的惯例,而不是下面其中一个替代方案。 * 一个替代规则是,在某些已存在的函数库, 总是使用 "-P"。 * 另一个替代规则是,在某些已存在的函数库, 总是使用 "?"。 当你开发一个函数时,你必须要与其它的函数保持一致。 当你开始一个新包时,在没有非常充分记录你的理由之前, 你应该不要使用这些替代规则。 ###前缀 因为AutoLisp的糟糕的名称空间管理,所以尽量使用一个特殊的前缀来避免变量冲突。 建议前缀: * lbfl- = lisp base function library * allib- =autolisp library * abflib- =autolisp base function library * BF- =base function (目前使用这个,主要是简单) ### 函数名 函数名应该包括处理对象的类型、处理目的。 示例: (defun BF-list-additem (lst index item) ...) ## 语言使用准则 ### 以函数式风格为主 不是必要的情况下,避免使用副作用。 Lisp 的最佳用法是"以函数式风格为主"。 避免改动局部变量,重新绑定试试。 ### 递归 你应该偏好迭代胜于递归。 因为递归很容易造成栈溢出。