本帖最后由 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的说明:
>- (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 是用于对象控制的。例如,
>- (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 为整数控制符,它们分别打印十进制、二进制、八进制、十六进制、基数。
>- (format nil " ~D ~B ~O ~X" 12 12 12 12)
" 12 1100 14 C twelve"
~E ~F ~G ~$为浮点数控制符,分别按照指数格式、定点式、浮点式、浮点定点结合方式。例,
>- (format nil " ~E ~F ~G ~$" 123450 123450 123450 123450)
" 1.2345E5 123450.0 123450. 123450.00"
> - (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 行,新一页。
> - (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却保留原值。
|