明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 11954|回复: 36

[【高飞鸟】] Make Lisp Great Again--利用隐藏函数恢复isp的活力!

    [复制链接]
发表于 2022-7-26 11:26:34 | 显示全部楼层 |阅读模式
本帖最后由 highflybird 于 2022-8-9 00:03 编辑

首先致谢:baitang36、tryhi、菜卷鱼等诸多大神!
自从隐藏的lisp被本论坛的一些大神发现后,LISP又重新恢复了活力。
套用川建国同志的一句话,隐藏函数 “Make Lisp Great Again”!
一、下面链接是关于隐藏函数的一些介绍和如何挖掘出来并加以应用:
激活系统隐藏的函数
给autolisp增加一种数据类型vector
用保留函数制作vlx
任意超大文件以原大小打包至VLX并极速释放(速度与硬盘写入速度一致)
本帖所提到的函数,不能直接在autolisp中使用,如何使用,请参考上面链接。
二、autolisp来源于common lisp,其中有很多隐藏函数也是common lisp的函数,这里着重介绍几个有用的:
1、Format函数
format函数是一个相当有用的函数,在许多编程语言均为格式化输出,譬如C语言的printf。
在autolisp中,如果要打印这样的格式化输出,你得用到多个princ函数,或者用strcat连接起来,并还得用一些数值转字符串的函数,这很不方便。
有了format函数,就会显得很简单了。当然你也可利用format函数格式化字符串。
下面一些链接为format函数的介绍。
lisp format总结
Common Lisp学习之十:输出格式化控制与高级循环控制
common lisp Format小结
Common Lisp入门笔记(二)赋值与输入输出
下面摘抄一段关于format的说明:
>
  1. (format   t   "~%The clever dog can do ~A + ~A =~A ." 2 3 5)

The clever dog can do 2 + 3 =5 .
NIL
Fortmat 的第一个参数是输出地,此例的参数 t 表示输出到 toplevel;第二个参数是输出格式串,~%
表示换行, ~A 表示该位置将用对应的参数进行替换。 Common Lisp 的打印格式串有多种控制符,如:
~A,~S,~P  是用于对象控制的。例如,
>
  1. (format t "~%TildeS prints ~S~%TildeA prints ~A " 'ACL::asymbol 'ACL::asymbol )

TildeS prints ACL::ASYMBOL
TildeA prints ASYMBOL  
NIL
此例应注意~A 与~S 差别。~S 可以打印出控制符,而~A 不能。~P 打印复数后缀”s”。
~D ~B ~O ~X ~R 为整数控制符,它们分别打印十进制、二进制、八进制、十六进制、基数。
>
  1. (format nil " ~D ~B ~O ~X" 12 12 12 12)

" 12 1100 14 C twelve"
~E ~F ~G ~$为浮点数控制符,分别按照指数格式、定点式、浮点式、浮点定点结合方式。例,
>
  1. (format nil " ~E ~F   ~G ~$" 123450 123450 123450 123450)

" 1.2345E5 123450.0   123450.      123450.00"
>   
  1. (format nil " ~E ~F   ~G ~$" 123.450 123.450 123.450 12.3450)

" 1.2345E2 123.45   123.45      12.35"
~n%,~n&,~|  为空白控制符,分别表示 n 换行,n-1 行,新一页。
>   
  1. (format nil "begin ~2% and   ~2&end")

"begin  


and   


end "
值得注意的是,在上述例子中,format 的第一个参数为 nil 时,打印执行后返回值不出现 nil;而参数
为 t 时,打印执行后返回值出现 nil> (SETF A (READ))  这就是所谓 Lisp 的副产品。
小惊喜:这个函数还可以直接进行数制之间的转化,不需要其他函数了,请看上面说明的第三条。
2、利用put和get函数为lisp添加一点面向对象编程。
值得注意的是lisp是一个函数式编程语言,并不是一个面向对象编程的语言,然而你还是可以利用某些函数添加面向对象的性质。
譬如赋予符号某些属性,下面有一些函数是可以用来存取符号的属性的。

get symbol property [Function]
This function returns the value of the property named property in symbol’s property list. If there is no such property, it returns nil. Thus, there is no distinction between a value of nil and the absence of the property.The name property is compared with the existing property names using eq, so any
object is a legitimate property.
See put for an example.
put symbol property value [Function]
This function puts value onto symbol’s property list under the property name property, replacing any previous property value. The put function returns value.
(put 'fly 'verb 'transitive)
)'transitive
(put 'fly 'noun '(a buzzing little bug))
) (a buzzing little bug)
(get 'fly 'verb)
) transitive
(symbol-plist 'fly)
) (verb transitive noun (a buzzing little bug))
symbol-plist symbol [Function]
This function returns the property list of symbol.
setplist函数不能用,我就不抄录了。
上面的用法,请读者自行练习和体会。
3、利用vector函数为lisp添加新的数据类型。
这个我不用介绍了,baitang36发现。链接:
给autolisp增加一种数据类型vector
关于lisp内部数据类型vector的小测试
4、其它可以用的一些common lisp函数:
nconc
adjoin
member-if-->相当于vl-member-if
member-if-not-->相当于vl-member-if-not
NREVERSE
concat
rassoc
list-elt
list-elt<-
等等,太多,不再一一列举。
这个是common lisp的参考手册,大家可以从中去寻找对你也许可能有用的函数。
如果大家找到了一些有用的,不妨分享给大家。

2022年8月3日补充:
5、日期相关函数:
下面的这两个函数以公元元年一月一日为零点计算日期和天数。
ymd->fix   年月日转为天数
例如:
(ymd->fix '(2022 8 3))  =>752403   ;公元元年距今752403天
(ymd->fix '(0 1 1))  =>0    ;公元元年元旦为0
(ymd->fix '(-1 12 30)) => -2   ;公元前的计算要加负号?
fix->ymd   天数转为年月日
(fix->ymd 752403)  =>(2022 8 3)
(fix->ymd 0) =>(0 1 1)   ;公元元年元旦
(fix->ymd -2) =>(0 1 -1)  ???不理解
有了这两个函数,就可以计算两个日期隔了多少天了。
譬如:
(- (ymd->fix '(2023 1 21))  (ymd->fix '(2022 8 3)))  =>173
离过年还要173天哦。
你也可以据此反推过了多少天后是什么日期。
刚验算,发现这两个函数不可靠!!!算了,当我白写了。
还有两个函数是
_days-after-build
_days-after-96
这两个函数没参数,一个是返回距CAD版本build日期天数,一个是返回1996年7月2日天数。在我的机器上测试如此,未验证其它机器。

因此在此特别强调:
一些隐藏函数不可靠,或者不安全,可能会导致CAD出错或崩溃!请大家慎用!!!
2022年8月8日补充:
6、字符串相关函数:
string-by-char-to-list
此函数可以用来做字符串分割,譬如:
(string-by-char-to-list "a,b,c,d,e,f,g" (ascii ","))
("a" "b" "c" "d" "e" "f" "g")
make-string
用来生成字符串,第一个参数为字符串长度,第二个参数为要填充的字符的ascii,譬如:
(make-string 12 (ascii "a"))
"aaaaaaaaaaaa"
string-fill
把某个字符串用指定字符填充,第一个参数为字符串,第二个参数为要填充的字符的ascii。
_$ (setq a "hello,world!")
"hello,world!"
_$ (string-fill a (ascii "a"))
"aaaaaaaaaaaa"
_$ a
"aaaaaaaaaaaa"
copy-string
复制字符串。
你也许会问,为何不直接用setq进行拷贝。它们还是有区别的。
举例,(setq a "hello,world!")
(setq b a)  用setq复制。
(setq c (copy-string a))
一开始它们是一样的,
但是如果你用内部函数修改了a的字符串值,
譬如(string-fill a (ascii "a"))
"aaaaaaaaaaaa"
_$ a
"aaaaaaaaaaaa"
_$ b
"aaaaaaaaaaaa"
_$ c
"hello,world!"
你会发现,b的值跟着改变了,而用copy-string的c却保留原值。


评分

参与人数 7明经币 +7 收起 理由
jltx123456 + 1 赞一个!
baitang36 + 1 很给力!
灬北方狼灬 + 1 很给力!
lee50310 + 1 赞一个!
print1985 + 1 神马都是浮云
yuanziyou + 1 很给力!
自贡黄明儒 + 1 赞一个!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下

本帖被以下淘专辑推荐:

发表于 2022-8-9 14:56:14 | 显示全部楼层
本帖最后由 llsheng_73 于 2022-8-9 15:05 编辑

(setq a "hello,world!")
(setq b a)  用setq复制。
(setq c (copy-string a))
一开始它们是一样的,
但是如果你用内部函数修改了a的字符串值,
譬如(string-fill a (ascii "a"))
"aaaaaaaaaaaa"
_$ a
"aaaaaaaaaaaa"
_$ b
"aaaaaaaaaaaa"

激活string-fill后是对的。。。如果用setq去改变a,那么b是不会变化的,看样子它和一些别的内部函数一样,隐藏了一些副作用,或者说有副产品
回复 支持 1 反对 0

使用道具 举报

发表于 2022-7-26 14:53:56 | 显示全部楼层
本帖最后由 菜卷鱼 于 2022-7-26 15:00 编辑

我贡献最小,跟真大神相提并论有点惭愧

adjoin  ;;;(adjoin item list) == (if (member item list) list (cons item list))
acons  ;;; (acons x y a) == (cons (cons x y) a)
butlast  ;;;去掉列表的最后一个元素 (reverse (cdr (reverse lst)))
code-char / char-code  ;;;相当于(rem int 256),跟ASCII相关,不知道有啥用
format   ;;; 格式化
funcall  ;;; (funcall '+ 1 2 3)  跟apply相比,不需要接一个表
reduce   ;;; (reduce '+ '(1 2 3) 4) 跟apply相比,后面可以多接一个原子
every   ;;; 等于vl-every
ldiff  ;;; 不知道具体啥用途
make-list  ;;; (make-list 5) (nil nil nil nil nil)
nconc  ;;;  (nconc x y) = (setq x (append x y)) 扩展 x
nreconc ;;; (nreconc '(1 2 3 4 5) '(6 7))=== (5 4 3 2 1 6 7)
nthcdr  ;;; 去掉前N个元素
revappend   ;;; (append (reverse x) y)
typep   ;;; (type 1 参数类型)  类型可以通过 type-of获取 ,相当于 (= (type a) 参数类型)
type-of  ;;; 获取参数类型
rassoc  ;;; (rassoc 'a '((a . b) (b . c) (c . a) (z . a))) => (c . a)
string-upcase ;;;大写 跟strcase 差不多
string-downcase  ;;;小写
string-capitalize  ;;; 英文单词,可以是英文句子的单词,首字母大写
string-equal  ;;;忽略大小写对比字符串
string-lessp  ;;;检查操作数的值是否单调递减。
rplaca  ;;(cons x (cdr lst))
rplacd  ;;(cons (car x) lst)
read-from-string  ;;;(read-from-string "abcde")==> ("abcde" . 5)    5是字符串长度
nreverse  ;;;; 应该跟 reverse 差不多 ,没仔细研究

defmacro   ;;;;能激活,不会用
defvar ;;;;能激活,不会用
defun  ;;;;能激活,不会用
let    ;;;;能激活,不会用

可以从附件里试

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 6明经币 +5 金钱 +5 收起 理由
tigcat + 5 很给力!
llsheng_73 + 1 很给力!
灬北方狼灬 + 1 很给力!
lee50310 + 1 赞一个!
print1985 + 1 赞一个!
自贡黄明儒 + 1 很给力!

查看全部评分

发表于 2022-8-9 13:45:16 | 显示全部楼层
本帖最后由 llsheng_73 于 2022-8-9 13:47 编辑
菜卷鱼 发表于 2022-7-26 14:53
我贡献最小,跟真大神相提并论有点惭愧

adjoin  ;;;(adjoin item list) == (if (member item list) list ...

(setq l1'(1 2)l2'(3 4))
(rplacd '(1 2)l2)=>'(1 3 4)
(rplacd l1 l2)完蛋了。。。。它会进入死循环,最后CAD崩掉。。。当然也可以在中途狂按ESC让它结束,会看到l1的值(1(1(1(1....(1 3 4)...))))
(rplacd (eval 'l1)l2)不会出现死循环的问题,并且把结果也给了l1(1 3 4)
这两点特别奇怪
(rplaca l1 l2)=>((3 4)2);;;等同于(setq l1(cons l2(cdr l1))),即把结果放回了第一个变量
(revappend l1 l2)=>(2 1 3 4)和(append(reverse l1)l2)完全相同,都不会修改l1或l2
(nreconc l1 l2)=>(2 1 3 4),但它同时把l1改为了(1 3 4)即(setq l1(cons(car l1)l2))修改了第一个变量但并不是这个函数的直接结果
发表于 2022-7-26 11:51:27 | 显示全部楼层
列出的都是隐藏函数吗?

点评

是  发表于 2022-7-26 11:52
发表于 2022-7-26 12:28:20 | 显示全部楼层
感谢版主共享资料!
发表于 2022-7-26 12:45:10 | 显示全部楼层
各位大师多来点通俗易懂的
实例科普一下
让我等小菜也能沾沾光
发表于 2022-7-26 15:02:37 | 显示全部楼层
(format   t   "~%The clever dog can do ~A + ~A =~A ." 2 35)   35中间少个空格
(format nil " ~D ~B ~O ~X ~R" 12 12 12 12 12)  原因:unknown format directive: "r" 位置-> 行:1 列:2  (~R 用不了,不知道为什么)

点评

谢谢指出!  发表于 2022-7-26 16:04
发表于 2022-7-26 15:41:14 | 显示全部楼层
很好玩的东西
发表于 2022-7-27 09:02:32 | 显示全部楼层
本帖最后由 自贡黄明儒 于 2022-7-27 09:43 编辑

我常常地想,autolisp设计者是哲学大师。比如C的while,有几种写法,而autolisp中while只有一种,便于掌握。C的while写法太多,使人花了更多时间去理解,而实际用处跟autolisp的一种写法是一样的;defun自定义的函数参数是固定的,也便于定义和掌握。
发表于 2022-7-27 10:55:24 | 显示全部楼层
感谢各位走在前沿的大神前辈,探索了更多的可能,拓宽了前进的道路。
无私的分享和奉献
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-23 04:23 , Processed in 0.232606 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表