- 博客(48)
- 资源 (9)
- 收藏
- 关注
原创 CLisp 31:调用C程序之外部函数
定义一个外部函数,然后输入#’name看结果,#,不同于FUNCTION和COMPILED-FUNCTION。函数SYSTEM::%PUTD,输入一个名称和一个函数对象,相当于定义一个函数。例如(system::%putd 'foo #'(lambda (x y) (+ x y))),相当于(defun foo (x y) (+ x y))。宏ffi::def-call-out就用它生成函
2013-01-22 22:34:08
1947
1
原创 CLisp 30:调用C程序之外部变量
用def-c-var定义的外部变量,其本质是一个宏,Symbol Macro。定义一个外部变量,然后执行(macroexpand ‘name),得到(FOREIGN-VALUE (LOAD-TIME-VALUE (GET 'NAME 'FOREIGN-VARIABLE))) (GET 'NAME 'FOREIGN-VARIABLE)的作用是获取符号NAME的属性FOREIGN-
2013-01-17 22:20:33
1275
原创 CLisp 29:调用C程序之回调函数
从LISP中调用C代码,再从C代码回调LISP的函数。有三种方式:通过输入参数传递函数指针;通过外部变量传递函数指针;编译时静态链接。 先看第一种方式,通过参数传递函数指针。 typedef int (*LispFunc) (int);__declspec(dllexport)int CallLispFunc1(int x, int y, LispFu
2013-01-16 20:43:44
1253
原创 CLisp 28:调用C程序详细指导
首先,介绍一下快速编译C代码生成DLL的方法,使用命令行。VC自带的工具Visual Studio .NET Tools > Visual Studio .NET 2003 Command Prompt。在这里可以使用程序cl.exe,在普通命令行窗口中用不了。因为是学习,为了方便只使用一个C文件,取名lisp.c,生成lisp.dll。命令很简单 cl.exe /LD lisp.c ,
2013-01-09 22:23:08
1424
原创 CLisp 27:处理正则表达式regexp
有很多处理正则表达式的组件,这里介绍Common LISP安装包自带的package regexp。不同组件的实现方式略有不同,对正则表达式的支持程度不同,但对外接口是相似的,可以举一反三。 直接匹配正则表达式的接口:(regexp:match pattern string ...) 先编译后匹配的接口:(regexp:regexp-compile pattern
2013-01-06 20:27:31
1620
2
原创 CLisp 26:测试框架fiveam
regression-test,别名rtest、rt,基本API为def-test、rem-test、do-test、do-tests。整个框架只有一个文件,2百多行,不依赖其他工程,非常轻便。用列表保存所有的测试用例,不支持用例分组。支持增量测试,即只执行失败的用例。 fiveam,强大的测试框架,支持很多特性,输出的结果更直观。依赖alexandria工程。
2013-01-02 22:17:24
976
原创 CLisp 25:可自由控制的字符窗口
CLisp的叫法为随机访问屏幕Random Screen Access。使用screen包提供的功能,可以打开一个像Edit编辑器一样的窗口,可以指定坐标输出字符串,键盘输入时没有回显。使用make-window打开窗口,返回一个窗口对象,最后使用close关闭窗口。通常使用with-window宏来打开窗口,可以保证窗口最终被关闭,改宏用变量*window*保存打开的窗口对象。窗口对
2012-12-23 17:48:45
1047
原创 CLisp 24:宏的本质也是函数
定义了一个宏,可以用macroexpand-1查看宏的展开式,这里介绍一种新的方法,有助于理解宏的本质。 [5]> (defmacro moo(x y) 首先定义一个宏,非常简单`(format t "~A : ~A~%" ,x ,y))MOO[6]> (moo 'asdf 'er) 执行宏,就是将输入的两个参数打印出来A
2012-12-16 20:46:25
1469
原创 CLisp 23:运行时修改函数的实现
运行时修改函数的实现,对LISP来说并不是稀奇事,用defun重新定义一个即可。这里介绍一个具体的、高级的做法,可以加深理解LISP函数的本质。例子很简单,只有几行代码,先定义一个函数foo,作用是乘方,然后再改掉foo的实现,新的实现仍然可以使用函数foo的原有实现。 (defun foo (x) (* x x)) (let*
2012-12-16 15:24:38
1457
原创 CLisp 21:模块化构建程序
如果开发一个稍微大一点的程序,就需要管理一大堆的LISP文件。编译顺序、加载顺序对LISP非常重要,顺序错了,要么加载失败,要么构建了错误的程序。模块化构建程序,就是把LISP源文件划分成多个模块,变成程序->模块->文件三层结构。 推荐使用用asdf管理Lisp程序模块,需要下载asdf.lisp,安装很简单,执行(require ‘asdf)即可。每个模块都要有一个描述文件,m
2012-12-15 18:51:12
1568
原创 CLisp 20:理解On-Lisp书中的延续continuation
什么是延续?在Windows、Linu等操作系统中,延续就是一个挂起的线程,包括线程挂起时的各种状态,CPU寄存器、堆栈、程序指针,可以恢复执行。在这里,程序是线形执行的,再加上各种跳转,函数返回也可看成跳转。在LISP语言中,一切都变得不同,这里没有程序指针,执行过程也不是线形的。只有函数、Lambda函数,延续也要用函数来表述。例如(* (+ 1 2) 3)),执行完加法后挂起了,挂起前可
2012-09-16 22:01:53
1353
原创 CLisp 19:On-Lisp书中延续和多进程的代码
先把代码放出来,以后解释其中原理 (defpackage my-proc (:use common-lisp)) (in-package my-proc) ;; 延续的代码 (defvar *actual-cont* #'values) (define-symbol-macro *cont* *actual-cont*) (defmacro
2012-09-11 21:27:07
1849
原创 CLisp 18:定义宏的宏,确定参数的前缀
实现宏时,最难理解的是反引号、逗号、和@符号,这里不重复基本的知识,而是介绍最难得部分“在宏里面定义宏”。即调用一个宏时,它会定义一个新的宏。一些例子中,会在宏参数前加逗号、引号、和@的复杂组合,怎么理解这些组合呢?这里用实验的方法来研究它们的作用,而不管什么规则、原理。先枚举各种组合:0 'x:引号1 x:没有符合2 ,x:逗号3 ,,x:两个逗号4 ',x:引号逗
2012-09-08 19:26:21
1755
原创 CLisp 17:恢复错误的再启动特性restart
再启动是一种处理错误的机制,比try-catch更强、更好。try-catch机制将错误处理分成两层,底层抛出异常,上层处理异常。restart机制将错误处理分成三层,底层抛出异常,中层提供多种处理方案,上层选择处理方案。restart并不是重新执行出错的代码,而是预测某段代码可能出错,在这段代码旁边放一个或多段替代的代码,基本代码出错后抛出异常,触发上层的异常处理代码,上层根据情况选
2012-09-01 21:57:42
970
原创 CLisp 16:抛出和捕捉异常,try-catch机制
函数error用于抛出异常,带一个参数,可以是字符串,也可以像format一样拼字符串,也可以是一个异常对象,也可以是指向字符串或异常对象的标识符,例如(error "some error")(setq x "some error") (error x)(setq y '(a b c)) (error "error info : ~A" y) 接下来用handler-ca
2012-08-30 21:12:26
1074
原创 CLisp 15:调用操作系统API例如kernel32.dll
前面介绍了如何在LISP中调用C语言编写的函数,而Windows操作系统的DLL也是C/C++语言编写的,其API使用C语言的命名规范,那么用同样的方法也能调用系统API。新建一个useapi.lisp文件,其内容如下(defpackage test-api (:use common-lisp ffi) (:export :cmd-line))(in-package te
2012-08-25 20:30:33
2696
原创 CLisp 14:在LISP中用FFI调用C语言的程序-成功了
用C代码实现一个DLL,可以用VC创建一个工程,让它生成lispcall.dll,导出一个整形变量和一个函数,函数里面随便写点什么。LISPC_API extern int x;LISPC_API int f(int v) { return v*v; } 再创建一个LISP源文件,写上下面代码(defpackage ffi-test (:use common-lisp ffi)
2012-08-24 21:13:01
5064
原创 CLisp 13:使用包FFI在CLisp中调用C语言写的函数
编译一个LISP文件,通常得到*.fas和*.lib文件,当LISP文件用到package FFI中的函数时,会生成一个*.c文件clisp\clisp.exe -K full -c source.lispclisp\full\lisp.exe -M lispinit.mem -q -c source.lisp source.lisp的内容:(defpackage "test-
2012-08-22 21:20:21
2417
原创 CLisp 12:使用CLisp的命令行模式的调试器
构造一个被零除的错误(/ 10 0)*** - /: division by zeroThe following restarts are available:ABORT :R1 Abort main loopBreak 1 [11]> 出现错误后怎么办呢,前面讲过按ctrl+d可以退出调试模式,这里讲怎么使用调试功能。先输入help看一下
2012-08-20 21:36:20
2568
原创 CLisp 11:使用 type-of 确定对象的类型
在LISP中定义一个加法函数(defun my-add (x y) (+ x y))但是,调用者可以输入任意类型的参数,导致异常。大部分情况下,调用者知道该输入什么类型的参数,但是,某些情况下需要函数内部校验输入参数的类型。这时就该使用 type-of 函数,type-of的返回值还真复杂,使用时要特别小心。 (type-of '()) => NULL(type-of
2012-08-18 21:42:43
891
原创 CLisp 10:用LISP的基本规则实现switch...case
Common LISP自带了case的实现,例如(setq x 'b)(case x) 返回nil(case x (a (print "it is a")) ((b c) (print "it is b or c")) (otherwise (print "it is not a b and c")))case的第一个参数是要判断的值,后面包含多个表达式,每个表达
2012-08-13 22:13:03
1898
原创 CLisp 9:获取系统环境变量,执行外部程序
获取操作系统的环境变量。(ext:getenv) 返回所有的环境变量(ext:getenv name) 返回名字为name的环境变量,如果没有定义的话返回nil 执行一个程序,必须关闭打开的程序才回到clisp命令行(ext:execute program arg1 arg2 ...)(ext:execute "notepad" "test.txt") 用记事本打开文件te
2012-08-12 21:26:31
1271
原创 CLisp 8:用LISP的基本规则实现while
要实现的while控制结构如下(用C/Java语言描述):while (test) body;要实现循环,要么用递归函数,要么用goto。用goto的等效实现如下:label: if (test) { body; goto label; } LISP的七个基本规则中没有goto,要介绍CLisp的新操作符tagbodytagbo
2012-08-12 21:19:53
2848
原创 CLisp 7:用LISP的基本规则实现if
LISP有7个基本规则,或7个基本函数,这里用他们实现if,在此过程中学一些知识为了覆盖系统自带的if,我们将名称改成if.(后面加一个点号)首先,定义一个名词为if.的函数(defun if. (test success &optional fail) (cond ((eq fail nil) (cond (test success))) ('t
2012-08-11 21:17:02
3187
原创 CLisp 6:通过TCP/IP连接远程执行命令
LISP有一个非常强的特性,程序即是数据,数据也是程序。函数eval可以解释并执行一段数据,例如 (eval '(+ 1 2 3) ) ,后面的 '(+ 1 2 3) 是数据,传给eval后执行得6。被执行的数据可以写在程序中,也可以从键盘、文件、网络连接读取,下面给一个例程,从网络连接读取数据并执行。 客户端程序net-client.lisp循环从键盘读取数据,并写到网络连接
2012-07-23 20:14:48
1234
原创 CLisp 5:用Socket包建立TCP/IP连接
建立TCP/IP连接的基本函数在SOCKET包中,调用函数时要在函数名前面加 socket : (冒号) 前缀服务器端可使用的函数(socket:socket-server 80) 建立监听程序,可以指定端口(socket:socket-server-close ss) 关闭监听程序(socket:socket-server-host ss) 返回Host属性(socket:s
2012-07-22 16:50:57
1501
原创 CLisp 4:读写文件
用函数open打开文件,返回文件对象,用close关闭文件。可以用read、write等命令读写文件,将文件对象作为参数传入即可。(open "d:\\test.txt") 读方式打开文件,文件不存在时报错(open "d:\\test.txt" :if-does-not-exist nil) 文件不存在时返回nil(open "d:\\test.txt" :element-type
2012-07-22 15:53:04
1454
原创 CLisp 3:简单的输入和打印
这里指从键盘输入参数,将结果输出到屏幕用于输入的函数有read、read-line、read-char、read-sequences用于输出的函数有write、write-line、write-string、fresh-line、write-sequence、format、printread和write:读写一个“S-表达式”,S-表达式就是Lisp的括号串read-line和wr
2012-07-21 21:38:45
1957
原创 CLisp 2:设置自己的工作环境
lispinit.mem是启动lisp必须的内存映像,如果启动是不指定内存映像,启动后很多函数都不可用,连(exit)都不可用,此时可按ctrl+d退出。可以通过定制内存映像文件,定制自己习惯的工作环境。例如,如果lisp不安装在C盘根目录,执行(compile-file "config")会失败,报找不到文件。修改lisp/src/config.lisp文件,修改defparameter *
2012-07-21 15:10:13
1495
原创 CLisp 1:安装和运行
LISP有很多的版本,称为不同的方言,其中还算有标准可循的是Common LISP可以安装clisp-2.49-win32-mingw-big.exe,比较容易获取,优快云上也有下载(无论下载哪个版本都差不多,初学者不会感觉到功能差异)有多种执行的方法 (1)执行clisp.exe,弹出一个下面的命令行窗口 i i i i i i i ooooo o
2012-07-20 22:23:03
5571
原创 学习boost模板编程:判断两个类型是否相同
boost/type_traits/is_same.hpp中的is_same模板,用于判断两个类型是否完全相同。首先,试一下下面函数的作用templatebool is_same_tester(T*, T*) { return true; }bool is_same_tester(...) { return false; }int a; char b;bool c = is
2012-01-12 23:03:39
3418
原创 学习boost预编译的代码:BOOST_PP_IS_EMPTY(X)
BOOST_PP_IS_EMPTY(X)这个宏判断输入参数X是否为空,例如 #define X 就定义了一个空的X,而 #define X 80 就不是空的。为了方便,将BOOST_PP_IS_EMPTY_DEF_简称为DEF_,将BOOST_PP_IS_EMPTY_HELPER简称为HELP。实现原理,将DEF_ X 空格 HELP 用##连接在一起。如果X为空,编译器会剔除掉空格,
2012-01-09 20:26:01
1244
原创 学习boost预编译的代码:查表法
【1】用宏的技巧,查表法查表法的作用是输入一个或多个参数,查表得到另一个参数,boost里面很多宏的实现都是查表法,例如BOOST_PP_BOOL(x) 将整数x转换成0或1BOOST_PP_INC(x) 将返回x+1BOOST_PP_DEC(x)返回x-1BOOST_PP_BITAND(x,y) 对两个bit进行与操作BOOST_PP_BITNOR(x,y) 对两个bit
2012-01-08 17:19:50
903
原创 学习boost预编译的代码
boost的代码很难看懂,从今天起每天看一点。【1】在通过编译前,查看宏置换的结果,即方便解决编译问题,又方便分析代码,方法如下#define STR(a) STR_I(a)#define STR_I(a) #aprintf(STR(SOME_MARCO(xxx)));再用此方法看看最难懂的宏之一 BOOST_PP_AUTO_REC的置换结果(注意包含对应的头文件) pri
2012-01-08 15:04:15
2341
原创 解读KeilC给C51程序自动添加的代码
<br />用KeilC编写C51的程序时,在执行main函数之前,还执行了一大段的代码<br />它们是用来清空内存、初始化全局变量的,下面是V3.3版本生成的代码<br /> <br />; 清空内存<br /> MOV R0,#0x7F<br /> CLR A<br />Label5:<br /> MOV @R0,A<br /> DJNZ R0,Label5<br /> MOV SP(0x81),#0x55<br /> LJMP InitVar<
2010-11-21 00:03:00
1083
原创 实现没有溢出问题的流水号
《多处理器编程的艺术》一书2.7节。在先到先服务的Baker Lock算法中,每个线程先领取一个代表到达顺序的编号,然后按编号服务。用递增的整数做编号时,会遇到整数溢出问题。为此,2.7节介绍了一种复杂的没有溢出问题的编号系统Unbounded timestamping sysem。在通知系统中,为保证消息处理顺序,都需要使用一个编号表示消息到达的顺序。用系统时钟是一个不错的办法,但系统时钟也
2010-03-10 22:43:00
705
原创 Matlab的图像细化算法(详细实现)
在目录matlab/toolbox/images/images/private下可以找到源代码。lutskel1.m,lutskel2.m,lutskel3.m,lutskel4.m,lutskel5.m,lutskel6.m,lutskel7.m,lutskel8.m,八个模板文件。applylutc.c,函数applylutc的实现,函数入口为mexFunction,执行图像细化算法时,会
2009-12-18 21:20:00
12775
1
原创 双尺度函数的理解
双尺度函数,又称二尺度微分方程、精细方程。找遍所有资料,都是直接给出方程式,没有一个资料对其来历做解释。本人理解如下,无资料为证。双尺度指得是两个尺度空间,双尺度函数是描述两个尺度空间的关系的函数。“双”和方程式中频繁出现的“2”没有关系。多尺度分析,又称多辨率分析,像俄罗斯套娃一样,定义了一系列的尺度空间。尺度空间的本质是满足特定条件的函数的集合,说到底是大量的函数。每个尺度空间都有一套
2009-12-12 22:20:00
7378
1
原创 算法:在两点间计算不相交的两条路由
在通信领域,为了保证信号不中断,经常需要为业务准备一条工作路由和一条保护路由。要求工作路由和保护路由没有交点,否则,相交点故障时,整个业务中断了。在Full Mesh网络中,很容易找到满足上面要求的两条路由。算法如下:1、先用最短路算法生成工作路由2、从图中去掉工作路由经过的节点3、再用最短路算法生成保护路由问题来了,当上面算法宣告失败时,并不等于问题无解。改进的算法:
2009-09-06 20:37:00
1472
1
原创 bison yacc源码解读(lalr.c)--求向前看符号的算法
/* Compute look-ahead criteria for Bison. Copyright (C) 1984, 1986, 1989, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.*/ #include #include "system.h"#include #
2009-05-06 22:55:00
2771
三连通算法和自动布局算法
2013-10-31
带约束点的最短路算法(自认为世界前沿的算法)
2013-05-21
不依赖OpenCV的SIFT特征点提取源代码
2013-05-05
多个18B20温度传感器同时工作
2010-11-28
带约束条件的最短路算法和KSP算法
2009-11-02
能够编译并生成C文件的bison2.4版本
2009-06-10
自己动手写YACC程序
2008-11-22
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人