第七章 函数的定义
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
7.1.5 自定义函数再开发专业 自定义函数再开发专业CAD软件中的应用 软件中的应用
1. 用于开发一些实用函数以补充系统内部函数的不足。 例如:画给定线宽bw的圆的函数 (defun kcircle (pc r bw) (command “pline” (polar pc 0 r) “w” bw “” “a” “ce” pc “a”359.99) )
函数最后一个标准表的求值结果。下面分别介绍用户函数定义与调用。 7.1.1 定义用户函数的函数 定义用户函数的函数DEFUN 1. 格式 (defun〈符号〉〈参数表〉 〈标准表1〉 〈标准表2〉 … 〈标准表n〉 ) 〈符号〉为所定义的函数的名称,它必须为符号原子: 〈参数表〉是所定义函数的参数,它包括两部分即形参和局部变量,这两部 分用“/”隔开,注意“/”与前后参数之间必须用空格分开。由于形参 和局部变量均可缺省,故有四种情况: (1) 二者均有(〈形参1〉〈形参2〉… / 〈局部变量1〉〈局部变2〉… ): (2) 只有行参(〈形参1〉〈形参2〉…); (3) 只有局部变量(〈局部变量1〉〈局部变量2〉…); (4) 二者均缺省即为空表〈〉。 形参是形式参数,在参数调用时要用实参代替。 〈标准表〉为函数定义的内容,是由一系列有序排列的标准表组成。
2.功用及求值结果 . defun 是Auto Lisp 的一个特殊函数。它的功能是定义一个用户函数,该函 数包括函数名、参数表及函数内容,defun不对任何自变量参数进行求值,仅仅 是建立一个函数的定义,它的返回值为用户函数名,例如: (defun jc (x y / a b) (setq a (+ x 15.0) b (+ y 100.0)) (setq z (* a 2.0 b)) ) 该例中jc为函数名,参数表中x、y为形参。a、b为局部变量,后面的两个 标准表为函数定义的内容。 如前所述,当此函数所在的LISP文件用Load函数调用内存时,该用户函数 并不执行,只是产生一个函数的定义,并返回该函数名(jc),jc被放在原子表 atomlist中,只有调用该用户函数时才执行函数的内容,并返回该函数的值。
又如:清屏函数 (defun clscl () (command “erase” “c” /(-1000 –100) /(4000 4000) “”) ) 再如:画任意曲线函数 (defun ryqx (/ pry) (prompt “\n”) (setq pry (getpoint “\n”)) (command “pline” pry “w” 0.4 “”) (while pry (setq pry (getpoint pry “\n”)) (command pry) ) (command “”) (command “pedit” “l” “f” “”) (redraw) ) 前面各章综合举例中的自定义函数均属于这类函数。对某一个专业 CAD系统可以将所定义的一些常用的专用函数放在一个公用函数文件中供 随时调用。
表中第一元素为用户函数名,8、12是与形参x、y相对应的实参。用户 函数调用时的求值过程是:Auto LISP的求值器首先对标准表中实参变元求值, 并用求值结果依次取代定义函数的形参,调用该函数定义,依次执行函数定 义的内容,即各标准表,并返回函数定义中最后一个标准表的求值结果。例 如jc函数调用时,将实参8、12代替形参x、y后,执行: (setq a (+8 15.0) (b (+ 12 100.0))
2. 在AutoLISP程序中利用自定义函数调用自定义函数以实现递归和循 环。例如:编程求一个整数n的阶乘n!。 其定义为:0!=1 n!=nx(n-1)! n≥1 (defun njc (n) (if (zerop n) l (* (progn (setq n (1- n)) (1+ n)) (njc n)) ) ) 这是一个自定义函数调用自身的程序,即利用自定义函数实现递归的例 子。 又如:循环修改输入参数的函数。 (defun csxg (/ e e1) (prompt “齿轮输入的参数p1,n1,i,z”) (initget “p1 n1 i z”) (setq e (read (getword “欲修改的参数:”)) (setq e1 (getreal “\n修改值?”)) (set e e1) (initget “Y N”) (setq ch 9stracase (getword “\n是否还要修改:”))) (if (= ch “Y”) (csxg)) ;(csxg)执行调用数据修改函数 )
7.1.2 函Biblioteka Baidu的调用
用户定义函数的调用形式和系统内部调用一样,也是通过一个标准表,表 的第一个元素为用户函数名,其它元素为实参,局部变量在函数调用时是不使 用的,其作用见下节函数的副作用。用户函数调用同时必须用实参代替形参, 而且参数的位置及数目应严格对应。例如,jc用户函数的调用格式为: (jc 8 12)
3. 利用cond函数调用自定义函数来实现对文本菜单的输入选项。例如: (defun igxx (/ ch) (princ “\n * * * * * *齿轮结构选型* * * * * * * * * *”) (print) (print “\n1……整体式”) (print “\n2……孔板式”) (print “\n3……辐板式”) (print “\n4……轮辐式”) (print) (princ “* * * * * * * * * * * *”) (initget “1 2 3 4”) (setq ch (read (getword “\n输入选项(1—4):”))) (cond ((= ch 1) (zts)) ((= ch 2) (kbs)) ((= ch 3) (fbs)) (T (lfs) ) ) 4. 建立专业CAD所需的图形库,并采用菜单等形式进行管理,这在 CAD应用软件开发中是十分重要的,关于这方面的内容请见第十二章。
第七章 函数的定义
Auto LISP程序是有一系列有序排列的标准表构成的。标准表的第一个元 素是函数名,所以Auto LISP程序是通过Auto LISP函数来实现的。Lisp语言又 称函数语言(Function Language)。Auto LISP提供了大量的函数,我们称之 为系统内部函数。随着Auto CAD版本的升级,系统内部函数也不断地增加。 但系统提供的内部函数再多,也难以满足各种不同专业的需要,必须由用户 自己开发。Auto LISP提供了用户自己定义函数的功能,即用户自己定义函数 的函数,这就为用户进行专业CAD的开发提供了极其有利的条件。Auto LISP 提供的函数定义的功能是是整个Auto LISP的核心部分。 自定义的函数是应用最广的函数。它一方面使程序者可根据自己的需要 开发大量用户函数,以弥补内部函数的不足,另一方面利用函数的定义可以 把Auto LISP程序,根据不同的功能分成很多功能的函数,或者叫子程序。这 样不仅有利于简化程序的编写,使程序结构紧凑,层次分明,避免重复,而 且增加了程序的可读性,便于程序的调试。 7.1自定义函数 自定义函数 用户自定义函数的过程包括函数定义和函数调用两部分。用户函数的定义 要用系统提供的内部函数DEFUN,利用它可以定义用户函数名,需要的形式 参数和函数的内容,其返回值为函数名。而用户函数的调用和系统内部函数 的调用一样,也要采用标准表的形式,其中第一项函数名也为用户定义的函 数名,其后的各项为用户函数要求的实参,实参要与形参严格对应,其返回 值为定义
第二种情况:(setq a 30.0 b 80.0 z 180.0) !a 30.0 !b 80.0 !z 180.0
7.1.4 使用 使用DEFUN的注意事项 的注意事项
1. 用defun函数定义函数名时,函数名不能与先前定义的函数同名,否则将取 代前面同名函数的定义。特别要注意的是不能用Auto LISP系统内部函数名和符 号作为自定义函数名,否则这些系统内部函数或符号将失去原有的定义。 2. 若自定义函数没有任何局部变量和形参,必须提供一个空表()或nil。例 如: (defun mf ()……) (defun mf nil……)
用defun定义的用户函数在调用同时,其主作用为返回一个函数值, 这个返回值是函数定义体中最后一个标准表的值。同时它也给一些变量赋 值,这是它的副作用,defun的副作用是比较重要的,下面作进一步的讨论。 Defun函数定义体中用到的两种变量: 1. 全局变量 所谓全局变量是指特定的函数调用后,仍保留其当前的约束值的变量 全局变量是指特定的函数调用后, 全局变量是指特定的函数调用后 只要该变量不重新赋值或不退出Auto CAD,全局变量的值一直保留在内存 中。且任何表达式均可使用它。对于某一个函数而言,凡是没有出现在参 数表中(无论在“/”之前或之后)的变量都是全局变量。例如上例中jc用 户函数体中z变量,它没有在参数表(x y / a b)中出现,因此,它是全局变 量,当jc函数调用后z的值为5152.000000。如果把jc的参数表改写为(x y / a),则对该函数定义来说,除z外,b也成为全局变量,其当前约束值为 112.0。必须注意,全局变量若在函数调用前已赋值,那么当函数调用后, 该全局变量的值已被改变了,即改变为函数定义体中赋给的当前约束值。 例如,z原来的值为2.0,当调用jc后其值变为5152.0。 2. 局部变量 对于一个函数来说,局部变量是指出现在参数表中的变量,它包括参 局部变量是指出现在参数表中的变量, 局部变量是指出现在参数表中的变量 数表中的形参和局部变量两部分, 数表中的形参和局部变量两部分,也就是说参数表中所列出的所有的形参 和局部变量都是该自定义函数的局部变量。 一个自定义函数的局部变量的约束值,只局限于该函数的内部, 一个自定义函数的局部变量的约束值,只局限于该函数的内部,而在 该函数的外部是无效的。 该函数的外部是无效的。现仍以jc函数为例说明之:
(defun jc (x y /a b ) (setq a (+ x 15.0) b (+ y 100.0) (setq z (* a 2.0 b)) ) jc函数中x、y、a、b的当前约束值分别为8、12、23、112.0,这四个局部 变量的约束值,只在jc函数调用过程中是有效的,当jc函数调用后,其当前约 束值均为nil。若局部变量在函数调用前已有值,例如a的值为30.0,b的值为 80.0,那么在jc函数调用时,这些变量的初值暂时被保存起来jc函数调用后局 部变量a、b又恢复原来的值30.0、80.0。 概括起来说一个自定义函数的局部变量的约束值的作用范围只限于该自 一个自定义函数的局部变量的约束值的作用范围只限于该自 定义函数内部,在函数的外部是不起作用的。 定义函数内部,在函数的外部是不起作用的。而自定义函数的全局变量的约 束值的作用范围不限于该函数的内部,在函数以外同样起作用。也就是说一 束值的作用范围不限于该函数的内部,在函数以外同样起作用 个函数的全局变量在函数调用后其约束值仍有效。假如该全局变量在函数调 用前已经赋值,那么在函数调用后,其约束值就永久地改变了。现仍举前面 例子来说明: 第一种情况:(setq a nil b nil z nil) (jc 8 12) !a nil !b nil !z 5152.000000
(setq z (* a 2.0 b)) 7.1.3 函数的副作用
返回值5152.000000
对于Auto LISP函数来讲,通常的用途是返回一个函数值,函数的返回值 经常作为其它函数的参数用,因此,必须熟练掌握每个函数返回值的类型。 否则编程容易出错。Auto LISP函数的返回值我们可以称之为函数的正作用。 但对有些函数来讲除了正作用外,还有函数的副作用,例如,setq函数 它不但有正作用,即返回一个函数值,而且还可以把一个表达式的值赋给一 个变量符号,这个作用我们称为setq函数的副作用。例如: (setq a 3.2 b (/ 16 2.0)) 返回值8.000000 同时它又给变量赋值如: !a 3.200000 !b 8.000000