当前位置: 首页 > 编程日记 > 正文

我也说说Emacs吧(6) - Lisp速成

前面我们学习了基本操作,也走马观花地看了不少emacs lisp的代码。这一章我们做一个lisp的速成讲座。

Lisp的含义是表处理语言。它的代码组成结构都是用括号组成的表来表示的。Lisp中的功能,要么是以函数形式求值,要么本身就是一些特殊表。
比如在Lisp语言中,判断分支的if不是语句,也不是函数,而是一种特殊的表。定义函数的方式,也是用一种叫做defun的特殊表。

Lisp基本函数速成

首先我们搭建一下环境,随便建一个.el为扩展名的文件。然后,我们写一个helloworld的代码吧:

(message (concat "Hello" "," "World" "!"))

我们把光标停留在这行上,然后执行C-x C-e,或者执行命令eval-last-sexp,结果就会在下边的状态栏上打印Hello,World.

下面函数的实验,我们就都采用这个方式来进行。

查找函数的帮助

将光标放到要查询的函数上,比如在message中,运行C-h f,就可以查询message函数的帮助文档。

算术函数

加法 +

例:

(message "%d" (+ 1 1))

减法 -

(message "%d" (- 1 1))

乘法 *

例:

(message "%d" (* 123456789 987654321))

注意,在emacs lisp中,数字是会溢出的。
例错误:

(message "%d" (* 123456789 3145926535897932384626433832795928841971))

会报下面的错:

  debug(error (overflow-error "3145926535897932384626433832795928841971"))

除法 /

需要注意的是,在emacs lisp中,除法结果是整数:

(message "%d" (/ 128.1 3.0))

结果是42

求余 %

需要注意的是,如果不是整数求余的话,会报错的。

例:

(message "%d" (% 128.1 3.0))

会报下面的错:

Debugger entered--Lisp error: (wrong-type-argument integer-or-marker-p 128.1)%(128.1 3.0)(message "%d" (% 128.1 3.0))eval((message "%d" (% 128.1 3.0)))

如果不知道integer-or-marker-p函数的含义,还是老办法,光标移到过去,然后运行C-h f(describe function)去查询它的文档。

加1 1+

例:

(message "%d" (1+ 1))

等价于

(message "%d" (+ 1 1))

减1 1-

与1+完全类似。
例:

(message "%d" (1- 1))

数学函数

求e的阶乘,exp函数

(message "%d" (exp 10))

结果是22026,请注意结果是整数。

求阶乘函数 expt

(message "%d" (expt 2 8))

结果是256,2的8次方。

求对数函数 log

如果给两个参数,那么就log a b,是求以b为底的a的对数。如果省略b,则默认值为e.

(message "%d" (log 256 2))
(message "%d" (log 100))

输出为8和4.

平方根函数 sqrt

(message "The square root of 128 is:%d" (sqrt 128))

输出为:

"The square root of 128 is:11"

求绝对值函数

(message "The absolute vaule of -1 is:%d" (abs -1))

输出为:

The absolute vaule of -1 is:1

三角函数

sin, cos, tan都是例行公事的函数,反函数是asin, acos, atan,

(message "%d" (sin 0))
(message "%d" (cos 0))
(message "%d" (tan 1))
(message "%d" (asin 1))
(message "%d" (acos 1))

逻辑运算

  • 两数逻辑与 logand
  • 两数逻辑或 logior
  • 两数逻辑异或 logxor
  • 两数逻辑非 lognot

例:

(message "%d" (logand 1 0))
(message "%d" (logior 1 0))
(message "%d" (logxor 1 0))
(message "%d" (lognot 0))

第一个1与0为0. 第二个1或0为1. 第三个1与0异或为1. 第四个0取非是-1.

逻辑运算特殊表

在实际编程中,用于与或非逻辑运算的是几个特殊表:

  • 与 and: 对每个参数进行求值,直到遇上一个nil
  • 或 or: 对每个参数进行求值,直到遇上一个非nil
  • 非 not:not是nil别名。其实取反就是判断一个逻辑值是否为nil.

比较函数

  • =: 等于
  • >: 大于
  • <: 小于
  • >=: 大于或等于
  • <=: 小于或等于
  • /=: 不等于
  • eq: 等于

例:

(/= (logand 1 0) (lognot 1))

判断函数

  • atom: 判断是不是一个原子
  • listp: 判断是不是一个列表
  • null: 判断是不是空
  • stringp: 判断是不是一个字符串
  • characterp: 判断是不是一个字符
  • symbolp: 判断是不是一个符号
  • zerop: 判断是不是0.
  • intergerp: 判断是不是整数
(atom ())
(listp ())
(null ())
(stringp "Hello")
(characterp "h")
(symbolp nil)
(numberp 1)
(zerop 0)
(integerp 1)

if特殊表

学习了若干判断函数,我们当然需要一个控制结构来使用它,这个控制结构就是if特殊表。if是个特殊表,而不是函数,当然对于我们初学使用来说,这个区别并不重要。
if特殊表的结构是(if 条件判断 THEN表 ELSE表 ... )
如果判断为非nil,则执行THEN表,否则执行ELSE表。
我们看个例子:

(if (atom ()) (message "() is an atom") (message "() is not an atom"))

输出当然是:() is an atom

cond特殊表

当条件特别多时,if特殊表嵌套可能会导致控制结构比较乱。这时我们可以使用cond特殊表来解决,cond特殊表的结构为:(cond 表1 表2 ...)
cond特殊表的会一直执行后面的表,直至遇到任何一个表的值为非nil为止。
每个cond中的表都是由两部分组成:判断条件和其他值。cond特殊表执行时,会首先检查判断条件是否nil,如果为nil则继续执行,否则就返回非nil表后面的值。
我们还是通过一个例子来学习:

 (cond ((= x y) "x and y are the same")((> x y) "x is greater than y")((< x y) "x is less than y"))

定义函数 - defun特殊表

学习了这么多预定义的函数,我们是不是也跃跃欲试,打算写几个自己定义的函数了呢?
Emacs Lisp的函数定义要比Common Lisp多几样东西。因为我们前面讲了,emacs lisp的函数就是我们正常调用的命令,所以它要定义交互方式,要定义函数文档。不过好在这两部分都是可选的,完全不知道的情况下,仍然能写出可以正确执行的函数来。

emacs lisp的defun特殊表的格式如下:
(defun 函数名 (形参列表) "可选的函数文档" (interactive;可选的交再继续方式)
函数体)

我们先写个简版的,实现判断一个数是不是偶数的函数:

(defun evenp (x)(if (= 0 (% x 2)) tnil))
(evenp 2)

我们再将其加上描述文档,同时加上一个是不是整数的判断:

(defun evenp (x)"Check if x is an even number or not"(if (and (integerp x) (= 0 (% x 2))) tnil))

到目前为止,虽然看起来用括号不太习惯,但是我们已经学会用defun特殊表定义函数,用if和cond特殊表来实现判断。好像也没什么复杂的嘛?

学习了之后再回头看我们之前贴过的代码,是不是一下子就好懂了很多呢?
比如这个set-mark-command,不就是几个cond特殊表的组合么:

(defun set-mark-command (arg)
...(cond ((eq transient-mark-mode 'lambda)(kill-local-variable 'transient-mark-mode))((eq (car-safe transient-mark-mode) 'only)(deactivate-mark)))(cond((and (consp arg) (> (prefix-numeric-value arg) 4))(push-mark-command nil))((not (eq this-command 'set-mark-command))(if arg(pop-to-mark-command)(push-mark-command t)))((and set-mark-command-repeat-pop(eq last-command 'pop-global-mark)(not arg))(setq this-command 'pop-global-mark)(pop-global-mark))((or (and set-mark-command-repeat-pop(eq last-command 'pop-to-mark-command))arg)(setq this-command 'pop-to-mark-command)(pop-to-mark-command))((eq last-command 'set-mark-command)(if (region-active-p)(progn(deactivate-mark)(message "Mark deactivated"))(activate-mark)(message "Mark activated")))(t(push-mark-command nil))))

遇到具体的函数,我们都可以通过describe-function函数去查看它的文档和代码。

我们先只求会用,有个感性的认识,之后基础回头再补。

小结

几个特殊表:

  • if特殊表:用来进行判断
  • cond特殊表:多分支判断
  • and特殊表:求值直到遇见nil为止
  • or特殊表:求值直到遇见非nil为止
  • defun特殊表:用来定义函数

有了上面的知识,分支、子程序结构都有了,我们可以像写命令式语言一样写代码了。

相关文章:

Matlab与数据结构 -- 如何获取给定目录中的文件

本图文详细介绍了Matlab中如何获取给定目录中文件的操作。

我的资源 分享区

把最近所做过一些程序都发上来。希望有用。已经上传了我的资源里面去了 第一期&#xff1a; 2007年制作的手机抽奖程序&#xff08;没完善版本&#xff09;&#xff1a; As 2.0 版本手机抽奖程序&#xff1a;http://dl4.csdn.net/fd.php?i60728776657431&s52b0082a4017dde…

软件测试概述--基础篇

文章目录软件测试概述软件测试基本概念软件测试的目的和原则软件测试的分类测试用例软件测试概述 软件测试基本概念 软件缺陷&#xff1a;俗话说就是bug。即计算机软件或程序存在某种破坏正确运行能力的问题、错误或者隐藏的功能缺陷。缺陷的存在会导致软件产品在某种程度上不…

Matlab与线性代数 -- 矩阵的连接

本图文介绍了Matlab中矩阵连接的cat方法。

Load balancer does not have available server for client

最近在研究spring-cloud&#xff0c;研究zuul组件时发生下列错误&#xff1a; Caused by: com.netflix.client.ClientException: Load balancer does not have available server for client: zuul-server 解决办法就是在pom文件里添加 <dependency> <groupId>or…

js 抛出异常 throw

netsuite中&#xff0c;有的时候在流程上我们需要控制&#xff0c;停止现有流程那么可以采取一种比较无奈的办法。 由于一些特殊情况&#xff0c;我们可以编写详细的流程控制&#xff0c;如netsuite销售人员可以审批一些SO单据&#xff0c;但并不是所有的SO单据他都能自己审批。…

leetcode--长按键入--python

文章目录题目题目详情示例解题思路思路代码运行结果最佳方案题目 题目详情 你的朋友正在使用键盘输入他的名字 name。偶尔&#xff0c;在键入字符 c 时&#xff0c;按键可能会被长按&#xff0c;而字符可能被输入 1 次或多次。 你将会检查键盘输入的字符 typed。如果它对应的…

Visual Studio 2008 每日提示(十四)

本篇包括tip131-tip140 http://www.watch-life.net/visual-studio/visual-studio-2008-tip-day-14.html #131、你为什么会把窗体设置成为浮动&#xff08;模式&#xff09; 原文链接:Why you would want to make a Tool Window Floating 如果你想把工具窗体放在一个特定的区域&…

mysql双机热备的实现

转&#xff1a;http://blog.csdn.net/qq394829044/article/details/53203645 Mysql数据库没有增量备份的机制&#xff0c;当数据量太大的时候备份是一个很大的问题。还好mysql数据库提供了一种主从备份的机制&#xff0c;其实就是把主数据库的所有的数据同时写到备份的数据库中…

Matlab编程与数据类型 -- 多维数组

本图文详细介绍了Matlab中的多维数组。

leetcode--最长连续递增序列--python

文章目录题目题目详情示例解题思路思路代码运行结果最佳方案题目 题目详情 给定一个未经排序的整数数组&#xff0c;找到最长且连续的的递增序列。 示例 输入: [1,3,5,4,7] 输出: 3 解释: 最长连续递增序列是 [1,3,5], 长度为3。 尽管 [1,3,5,7] 也是升序的子序列, 但它不是…

va_start() va_end()函数应用

1:当无法列出传递函数的所有实参的类型和数目时,可用省略号指定参数表void foo(...);void foo(parm_list,...);2:函数参数的传递原理函数参数是以数据结构:栈的形式存取,从右至左入栈.eg:1 #include <iostream>2 voidfun(inta, ) 3 { 4 int*temp &a; 5 temp; 6 for(i…

高考估分查分选志愿一键搞定_支付宝又操办了件人生大事

摘要&#xff1a; 可能比高考更考验心力的填报志愿&#xff0c;支付宝要帮你一键搞定。 支付宝今天正式上线集估分、查分、选志愿等众多服务于一体的高考后综合服务平台&#xff0c;陪伴高考学生的青春大考。考生在估分、查分后&#xff0c;还可以看到系统智能推荐供参考的合适…

LSGO:祝大家新年快乐!

2016年&#xff0c;团队做了很多事&#xff0c;有做成的&#xff0c;有没做成的&#xff0c;有正在推进的&#xff0c;有主动放弃的&#xff0c;有做的好的&#xff0c;有做的不好的&#xff0c;但总体上还是做了很多的事情。希望2017年能做更多一点的事情&#xff0c;好的做的…

VMware安装Centos7桌面版超详细图文过程

前提准备&#xff1a; VMware Workstation虚拟机 centos7.4 镜像&#xff08;我下载的DVD版4.1G&#xff09; 打开VM&#xff0c;点击文件->新建虚拟机 不是说你分给虚拟机2G内存&#xff0c;主机就少了2G的内存。比如说假设主机内存为8G&#xff0c;虚拟机关闭的时候&…

关于ASP.NET Web 部件连接的引入

创建用于 ASP.NET 2.0 应用程序的 Web 部件 您可以用两种方法创建 Web 部件。第一种方法涉及创建一个自定义的 Web 部件类&#xff0c;该类从 System.Web.UI.WebControls.WebParts 命名空间中定义的 WebPart 类继承。使用该方法时&#xff0c;将自定义的 Web 部件类打包到一个程…

hive2.1.1安装配置

2019独角兽企业重金招聘Python工程师标准>>> 一、Hive 运行模式 与 Hadoop 类似&#xff0c;Hive 也有 3 种运行模式&#xff1a; 1. 内嵌模式 将元数据保存在本地内嵌的 Derby 数据库中&#xff0c;这是使用 Hive 最简单的方式。但是这种方式缺点也比较明显&am…

高斯消元法对矩阵LU分解的影响

** 欢迎大家到Matlab与线性代数专栏中查看相关图文。 ** 本文详细介绍了Matlab进行lu分解操作时l不为三角形的原理。

Windows10下SSH远程拷贝文件

因为今天需要把服务器上面的东西备份一下&#xff0c;自己平时也在windows下面做的测试&#xff0c;所以用windows在服务器拷贝文件到本地。 首先需要下载一个工具pscp.exe 下载链接 然后再把它移动到这个目录下面就行了 WINR打开命令行 pscp -r 用户名ip:/root/flask E:/refl…

如何在Matlab中获取函数参数的数目?

本图文详细介绍了Matlab中获取函数参数数目的方法。

新站测试中欢迎访问

想买画的可以来看看哦 www.oneartone.com 转载于:https://www.cnblogs.com/liugod/archive/2009/01/04/1368082.html

FTP匿名访问修复方法

window2003 window2008

LeetCode Python题解(一)----双指针法

根据&#xff1a; github优秀创作者. 算法思想 1.双指针法 2.排序 3.贪心思想 4.二分查找 5.分冶 6.搜索 7.动态规划 8.数学 1. 双指针法&#xff1a; 双指针主要用于遍历数组&#xff0c;两个指针指向不同的元素&#xff0c;从而协同完成任务。 1.1 有序数组的 Two Sum 题…

解密淘宝网的开源架构(转)

淘宝网&#xff0c;是一个在线商品数量突破一亿&#xff0c;日均成交额超过两亿元人民币&#xff0c;注册用户接近八千万的大型电子商务网站&#xff0c;是亚洲最大的购物网站。那么对于淘宝网这样大规模的一个网站&#xff0c;我猜想大家一定会非常关心整个网站都采用了什么样…

不上全站https的网站你们就等着被恶心死吧

2019独角兽企业重金招聘Python工程师标准>>> 测试脚本 #!/bin/sh wget \ --user-agent"Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19" \-r \-P a…

《C#精彩实例教程》小组阅读01 – MSDN是什么?

学习编程&#xff0c;特别是在Windows环境下的编程&#xff0c;当我们遇到问题时&#xff0c;最先想到的权威解答机构就是MSDN了。 什么是MSDN呢&#xff1f; MSDN – Microsoft Developer Network 是微软一个期刊产品&#xff0c;专门介绍各种编程技巧。同时它也是独立于Mic…

LeetCode Python题解(二)----排序

根据&#xff1a; githhub优秀创作者. 算法思想 1.双指针法 2.排序 3.贪心思想 4.二分查找 5.分冶 6.搜索 7.动态规划 8.数学 快速排序 用于求解 Kth Element 问题&#xff0c;也就是第 K 个元素的问题。 可以使用快速排序的 partition() 进行实现。需要先打乱数组&#xff…

人生快乐之道(组图)

举报 转载于:https://www.cnblogs.com/qqnnhhbb/articles/1373323.html

Codeforces Round #270

Codeforces Round #270 题目链接 A&#xff1a;我是筛了下素数。事实上偶数仅仅要输出4和x - 4&#xff0c;奇数输出9和x - 9就可以 B&#xff1a;贪心的策略&#xff0c;把时间排序后。取每k个的位置 C&#xff1a;贪心。每次遇到一个人尽量让他用字典序小的&#xff0c;假设不…

Matlab与数据结构 -- 如何获取完整文件名

本图文介绍了Matlab中获取完整文件名的函数fullfile()。