首页 > 其他分享 >Emacs折腾日记(四)——elisp控制结构

Emacs折腾日记(四)——elisp控制结构

时间:2024-12-17 21:53:09浏览次数:6  
标签:语句 代码 elisp 控制结构 fib Emacs setq 使用

目前我们接着学习elisp相关语法,这里我是按照 elisp 简明教程 来进行学习。与其说这是我自己写得教程到不如说是在这个上面做得注释。目前我不知道这样是否侵犯相关的知识产权。目前就先这样继续学习,继续写记录吧。

闲话少说,进入本篇的正题,关于elisp的控制结构。一般编程语言都有三种控制结构:顺序结构、条件结构、循环结构。elisp同样有这三种控制结构。

顺序结构和复合语句

一般默认elisp的语句是顺序执行的,例如下面的代码

(setq name "Emacs")
(message "hello, %s" name)

它先执行前面的 setq 语句,先给变量name 定义并赋值为 Emacs 。后面接着执行第二行代码,调用message 函数来输出一段文字。

在其他语言一般都有一个复合语句。它是有多个语句共同组成的,例如 C/C++中使用{} 来将多个语句整合成一条复合语句。针对C/C++ 我们在很多地方会用到复合语句。例如如果 if , while 等语句后只需要一条语句,那么可以直接使用一条语句,例如下面的代码

// 这么写代码不太正规但是符合语法规范,也能编译过
int main()
{
    int i = 0;
    while(i++ < 10)
        printf("%d\n", i); //打印1到10,这么10个数字

    return(0);
}

但是如果在循环或者if条件成立后,执行多条语句,就需要使用复合语句,也就是用大括号括起来。

那么在elisp中也有这样的操作,在条件和循环语句中需要执行不止一条语句,也需要使用复合语句。

elisp 中符合语句使用 progn 来包含一组语句组成复合语句,它的语法规则是

(progn
	statement1
	statement2
	...
	statement3)

例如我们将上面的代码用 progn 包装一下

(progn
	(setq name "Emacs")
	(message "hello, %s" name)) ;; => "hello, Emacs"

使用 progn 包装的复核语句可以使用 C-x C-e 也就是 eval-last-sexp 来同时执行里面的两个子语句。如果我们将它们分开写,则使用 eval-last-sexp 做不到这点,它只能一条条的执行

条件语句

我们使用 ifcond来表示条件分支,if的语法如下

(if condition
	then
else)

需要注意的是 这里的 thenelse 并不是关键字,而是对应的语句,也就说紧跟着if条件的语句表示条件成立时执行的代码,下一条则是条件不成立时执行的代码。例如我们使用下面的代码来获取两个数的最大值

(defun get-max(a b)
	(if (> a b)
		a
	b))

(get-max 3 4) ; => 4

与 C/C++ 的函数不同,elisp 函数的返回值不需要使用 return 或者其他的关键字特意指出,它是将函数最后执行的语句的返回值作为函数的返回值,这里当 a > b 时条件成立,执行 a 然后结束函数,也就是这个时候函数的最后一个语句是 a ,函数返回 a 的值。否则执行 b ,此时函数的最后执行的语句就是 b ,这个时候函数就返回 b 的值

cond 有点像 C/C++ 中的 switch ,它的语法如下

(cond (case1 do-when-case1)
      (case2 do-when-case2)
      ...
      (t do-when-none-meet))

它的语法特点是,它与 switch 类似,由一堆 casedefault 组成。每个case 都使用一对 () 来区分,最后可以使用 t 来表示未匹配到前面的 case 时执行的语句,类似于default语句。这里我们使用当初学习C/C++ switch 语法时的经典代码来作为示例

(defun score-report (score)
        (cond ((>= score 90) "优秀")
              ((>= score 80) "良好")
              ((>= score 60) "及格")
              (t "不及格")))

(score-report 75); => 及格

我们可以看到,cond 语句的使用比 switch 更为的灵活,switch case 只能进行整型变量的相等比较,而 cond 可以进行其他变量类型的不同形式的条件判断,它只是在形式上更像 switch,但是在使用的范围上更像 if-else if-else。另外 elisp 简明教程中 提供了一个使用 cond 计算 斐波那契数列的例子

(defun fib(n)
        (cond ((= n 0) 0)
              ((= n 1) 1)
              (t (+ (fib (- n 1)) (fib (- n 2))))))
(fib 10) ; => 55

因为 elisp 中使用 setq 来进行赋值操作,所以它里面的= 就是数学意义上比较相等的操作符,而 其他语言中的 == 在lisp中无效。这里如果写成 == 将会报错。

上面的例子也很好理解 当 n 等于 0时返回0,等于 1 时返回1,否则返回 fib(n - 1) + fib(n - 2) 使用 C/C++ 的话可能更容易理解

int fib(int n)
{
	if(i == 0)
		return 0;
	else if (i == 1)
		return 1;
	else
		return fib(n - 1) + fib (n - 2)
}

循环结构

循环使用 while 关键字,它的语法结构如下

(while condition
  body)

我们可以将上述循环打印的C代码使用 elisp 实现

(setq i 0)
(while (< i 10)
	(progn 
		(message "%d" i)
		(setq i (+ i 1))))

我们执行完代码之后使用 switch-buffer,切换到 *message* ,可以看到它打印了从0到9的数据。上面的斐波那契数列的例子我们可以使用 while 来实现

(defun fib (n)
  (cond ((= n 0) 0)
        ((= n 1) 1)
        (t (let ((first 1)
             (second 1)
             (third 1))
             (setq n (- n 2))
             (while (> n 0)
               (progn
                 (setq third (+ first second))
                 (setq first second)
                 (setq second third)
                 (setq n (- n 1))))
             third))))

(fib 10) ; => 55

因为 elisp 中没有提供 += ++ 这样算术运算符,所以我们需要使用 setq 来赋值。

下面还有一个计算阶乘的例子

(defun factorial (n)
  (let ((res 1))
    (while (> n 1)
      (setq res (* res n))
      (setq n (- n 1)))
    res))

(factorial 10) ; => 3628800

我们也可以提供一个递归的版本

(defun factorial (n)
  (if (= n 1)
      1
  (* (factorial (- n 1)) n)))

(factorial 10) ; => 3628800

到此为止,本篇就结束了。本篇涉及到的elisp 代码其实也不算复杂,如果能熟练掌握一门编程语言的话,到此为止的代码应该不算太难理解。在编写这些示例代码的时候我觉得还好,主要注意括号的匹配,算法什么的就是照搬C/C++中一些经典写法就差不多了。但是即使上面的代码并不多,代码量并不大,我也能明显感觉到上述代码在阅读上不那么直观。

标签:语句,代码,elisp,控制结构,fib,Emacs,setq,使用
From: https://www.cnblogs.com/lanuage/p/18613479

相关文章

  • Emacs折腾日记(三)——简单的elisp 入门
    Emacs本身的使用并不复杂,利用帮助文档,差不多半小时左右就能把一些常见的操作方式和快捷键过一遍,剩下的就是慢慢使用并且熟悉了。Emacs真正有价值的是它高度的客制化。任何人都可以利用elisp代码将Emacs改造成只属于自己的编辑器。会elisp的不一定是高手,但是高手没有一个是不会el......
  • Emacs 折腾日记(二)——Emacs简单入门
    环境准备这里我们根据之前博客配置的wsl2+archlinux环境,安装Emacssudopacman-Semacs如果之前配置的关于gui的部分正确,那么在终端输入emacs来启动或者在Windows的开始菜单中能找到emacs(Arch)之类的启动项目。当然你也可以使用emacs-nw来开始一个终端的emacs程序......
  • C:数据类型、控制结构
    基本语法概述C语言程序里大括号可以用来代表函数(函数可以看作一组语句)C语言里每个函数都必须有名字,不同函数的名字不能相同C语言程序必须包含一个叫做main的函数,这个函数叫做主函数(入口函数)程序从主函数的第一条语句开始执行,当主函数里最后一条语句结束后整个程序结束函......
  • win11安装emacs+igc+mps
    gitclonehttps://github.com/kiennq/emacs-buildcdemacs-build.\emacs-build.cmd--slim--clone--deps--variantmps--build--branchscratch/igc--with-mps--pdf-tools--hunspell--mu--isync--pack-all--with-tree-sitter=ifavailable当msys2装好后强制退......
  • 【Emacs】使用全教程
    Emacs入门:使用全教程启动Emacs要进入Emacs,只需输入其名称:$emacs:-:-C-z挂起EmacsC-xC-c永久退出Emacs全局描述:-:-C-<key>表示按住控件,然后按<key>M-<key>表示按Esc一次,然后按<key>移动返回向前要移动的实体C-bC-fHaract......
  • Java流程控制结构中的分支结构
    分支结构目录分支结构if...else分支结构switch-case分支结构在Java编程中,分支结构是控制程序流程的重要工具,它允许程序根据不同的条件执行不同的代码块。Java提供了两种主要的分支结构:if-else和switch-case。本文将详细介绍这两种结构的工作原理、语法规则以及实战应用,帮助读者......
  • Emacs有什么优点,用Emacs写程序真的比IDE更方便吗?
    Emacs是一种强大的文本编辑器,有许多优点,使其在某些方面比传统的集成开发环境(IDE)更方便。以下是一些使用Emacs的优点:1.高度可定制性Emacs可以通过EmacsLisp编程语言进行高度自定义。你可以根据自己的需要修改和扩展Emacs的功能,几乎没有限制。2.统一的工作环境Ema......
  • 走进Emacs,优缺点
    Emacs,全称为EditorMACroS(编辑器宏),是一款历史悠久且功能强大的集成开发环境和文本编辑器。自1975年由RichardStallman(理查德·马修·斯托曼)与GuySteele在麻省理工学院(MIT)的人工智能实验室(AILab)共同开发以来,Emacs一直以其高度的可定制性、扩展性和丰富的功能而受到程序员和其......
  • 用Emacs写程序真的比IDE更方便吗?
    探讨Emacs写程序是否比IDE更方便,是一个深入且主观的话题,因为它涉及到个人的工作习惯、项目需求、技术偏好以及对工具的熟悉程度。以下是对这一问题的详细分析,旨在从多个角度探讨Emacs与IDE在编程中的优劣,并尝试回答这一问题。一、引言在软件开发领域,集成开发环境(IDE)和文本编......
  • Emacs的优点,用Emacs写程序真的比IDE更方便吗?
    Emacs是一个经典的文本编辑器,以其强大的扩展性和灵活性而闻名。虽然在当今的软件开发行业中,集成开发环境(IDE)如VisualStudio和IntelliJIDEA占据了主导地位,Emacs依然保持着一定的独特优势和忠实用户群。在这篇文章中,我们将探讨Emacs的主要优点,并评估在现代编程实践中,使用Emacs......