初识LISP(1)——基本的结构、语法与数据类型

2024-02-08 12:32

本文主要是介绍初识LISP(1)——基本的结构、语法与数据类型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       既然下定决心学习LISP,我计划学习LISP的过程都以博客的形式做总结。当然是需要参考学习网上的教程,网上的教程讲解的比较详细。而我打算以自己的理解来做尽可能简洁的总结,一方面将自己的学习过程做一个回顾,另一方面,如果日后忘记了什么知识点,也方便查询。

一、LISP—程序结构

      首先lisp很独特的一点就是圆括号,程序自始至终都是圆括号,例如函数、表达式……这一特色的功能与Java的花括号“{}”和Python的缩进功能类似。LISP的前缀表示方法类似于栈的概念,即a+b,写作(+ a b),下面第一句就是实现(3+5)/2,值得注意的是运算符和数字之间必须以空格间隔开,这是最基本的语法要求。

(print (/ (+ 3 5) 2))
(format t "~%");打印一个换行符
(write-line "Hello World!");最经典的,打印“Hello World!”


二、LISP—基本语法

       这里需要记住的是LISP的三个基本块:原子、列表和字符串。原子可以理解成编译器视角下的单一元素,可以由数字、字母和特殊字符组成。而列表是包含原子与子列表的序列。字符串是由双引号括起的字符。

      需要注意的是1.LISP语言不区分大小写;

                              2.过去调用函数的方式为f(x),而在LISP的世界一切都是平等的,写作(f  x);

                              3.只有三种类型的元素是常数,返回的是自己的值:数字;字母t,代表逻辑真;nil,代表逻辑假,还有一个空的列表。

     LISP允许名字里包含数字,但是也别过分到都是数字,这样编译器只能认为这是数字了好吧。之前说原子里可以包含特殊字符,比如什么双引号、冒号什么的,那么也需要有转义字符的,转义字符是()。

     最后值得一提的,先看代码:

(write (* 2 3));这行代码会打印出乘法结果6,而如果要打印出(* 2 3),也就是不进行求值,那可以通过以下代码实现(write ' (* 2 3));没错,就是加一个单引号在前面~~其实想实现这个功能还有一种办法的(format t "(* 2 3)");最传统的打印字符串的好吧,其实也就是打印原子或列表的字面结果。

三、LISP—数据类型

   类型说明符是数据类型的系统定义的符号。

array fixnum package simple-string
atom float pathname simple-vector
bignum function random-state single-float
bit hash-table ratio standard-char
bit-vector integer rational stream
character keyword readtable string
[common] list sequence [string-char]
compiled-function long-float short-float symbol
complex nill signed-byte t
cons null simple-array unsigned-byte
double-float number simple-bit-vector vector
     

      没有什么可说的,类型说明符也只能等以后遇见什么再聊吧。先看几行代码吧:

(setq a 10)(print a);前一句可以理解成a是10的变量引用,这里打印了a(setq b 20)(print (type-of b));

输出结果为

(INTEGER 0 281474976710655) 

       很显然这里输出的b的类型,而后面的两个数代表的是b的值在这个范围内,后面那个数肯定是有背景的,换算成十六进制即为FFFF FFFF FFFF ,可以尝试一下当输入为

(setq x 281474976710656)  ;构建一个符号指定一个值
(setq x 281474976710657)
(print (type-of x));分别运行上面的代码,得到的都是  (INTEGER (281474976710655))  ,即是变量的值大于这个临界值。



四、LISP—宏

       我觉得这里的宏完全可以当做函数对待,宏的定义是使用defmacro来实现的。

;宏定义(defmacro setTo10(num)(setq num 10)(print num))
(setq x 25)
(print x)
(setTo10 x)



五、LISP—变量

       全局变量是通过defvar来定义的,而局部变量有三种结构可以创建:setq、let和prog


(defvar x 123)
;(print x)
(write x)(setq x 10)
(setq y 20)
(format t "x = ~2d y = ~2d ~%" x y);类似于C语言的形式,大概理解是令t指向总字符串
(format t "x = ~2d y = ~2d " x y);“~%”是换行作用,~2d是两位整型数



;局部变量的使用,分别定义的x、y和z之间不互相冲突(let ((x ' a)(y ' b)(z ' c))
(format t "x = ~a ~% y = ~a ~% z = ~a ~%" x y z))(prog ((x ' (a b c))(y ' (1 2 3))(z ' (p q 10)))
(format t "x = ~a ~% y = ~a ~% z = ~a" x y z));~b是输出二进制编码,~a是输出字符


六、LISP—常量

        常量通过defconstant声明得到,defun即是定义函数。

;声明圆周率为全局常量,定义一个得到圆面积的函数
(defconstant PI 3.141592)
(defun area-cirlce(rad)(terpri)(format t "Radius = ~5f" rad)(format t "~%Area = ~10f" (* PI rad rad)))
(area-cirlce 10)


七、LISP—运算符

      运算符是一个符号,它告诉编译器执行特定的数学或逻辑操作。其中对数据的运算操作归类为四种:算术运算、比较操作、逻辑运算和位运算。

算术运算:

运算符 描述 Example
+ 增加了两个操作数 (+ A B) = 30
- 从第一数减去第二个操作数 (- A B)= -10
* 乘两个操作数 (* A B) = 200
/ 通过取消分子除以分子 (/ B A) = 2
mod,rem 模运算符和其余整数除法后 (mod B A ) = 0
incf 递增运算符,所指定的第二个参数增加整数值 (incf A 3) = 13
decf 递减操作符,通过指定的第二个参数减小整数值 (decf A 4) = 9


比较操作:

Operator 描述 Example
= 检查如果操作数的值都相等与否,如果是的话那么条件为真。 (= A B)= true.
/= 检查如果操作数的值都不同,或没有,如果值不相等,则条件为真。 (/= A B) =true.
> 检查如果操作数的值单调递减。 (> A B) !=true.
< 检查如果操作数的值单调递增。 (< A B) = true.
>= 如有左操作数的值大于或等于下一个右操作数的值,如果是则条件检查为真。 (>= A B) !=true.
<= 如有左操作数的值小于或等于其右操作数的值,如果是,则条件检查为真。 (<= A B) = true.
max 它比较两个或多个参数,并返回最大值。 (max A B) 返回20
min 它比较两个或多个参数,并返回最小值。 (min A B) 返回 20

布尔值逻辑操作:

运算符 描述 示例
and 这需要任意数量的参数。该参数是从左向右计算。如果所有参数的计算结果为非零,那么最后一个参数的值返回。否则就返回nil。 (and A B) = NIL.
or 这需要任意数量的参数。该参数是从左向右计算的,直到一个计算结果为非零,则此情况下返回参数值,否则返回nil。 (or A B) = 5.
not 它接受一个参数,并返回t,如果参数的计算结果为nil。 (not A) = T.

对数位运算操作:

操作符 描述 Example
logand 这将返回位逻辑的参数和。如果没有给出参数,则结果为-1,这是该操作的标识。 (logand a b)) = 12
logior 这将返回位逻辑包括它的参数或。如果没有给出参数,那么结果是零,这是该操作的标识。 (logior a b) = 61
logxor 这将返回其参数的按位逻辑异或。如果没有给出参数,那么结果是零,这是该操作的标识。 (logxor a b) = 49
lognor 这不返回的逐位它的参数。如果没有给出参数,则结果为-1,这是该操作的标识。 (lognor a b) = -62,
logeqv 这将返回其参数的逐位逻辑相等(也称为异或非)。如果没有给出参数,则结果为-1,这是该操作的标识。 (logeqv a b) = -50

        这里就只给出算术运算和比较运算的代码,其中对数位运算就是以二进制数之间进行与、或、异或等操作,然后运算的结果以十进制的形式输出。

;运算符,算术运算
(setq a 10)
(setq b 20)
(format t "~%和:~d" (+ a b))
(format t "~%差:~d" (- a b))
(format t "~%积:~d" (* a b))
(format t "~%商:~d" (/ a b))
(format t "~%取余:~d" (mod a b))
(format t "~%取余2:~d" (rem a b))
(format t "~%加的和:~d" (incf a 3))
(format t "~%减的差:~d" (decf a 5))
;比较运算
(format t "~%是否相等? ~a" (= a b))
(format t "~%是否不等? ~a" (/= a b))
(format t "~%是否小于? ~a" (< a b))
(format t "~%是否大于? ~a" (> a b))
(format t "~%是否大于等于? ~a" (>= a b))
(format t "~%是否小于等于? ~a" (<= a b))
(format t "~%最大值? ~a" (max a b 15 30))
(format t "~%最小值? ~a" (min a b 15 30))




















这篇关于初识LISP(1)——基本的结构、语法与数据类型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/691053

相关文章

基本知识点

1、c++的输入加上ios::sync_with_stdio(false);  等价于 c的输入,读取速度会加快(但是在字符串的题里面和容易出现问题) 2、lower_bound()和upper_bound() iterator lower_bound( const key_type &key ): 返回一个迭代器,指向键值>= key的第一个元素。 iterator upper_bou

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

Linux操作系统 初识

在认识操作系统之前,我们首先来了解一下计算机的发展: 计算机的发展 世界上第一台计算机名叫埃尼阿克,诞生在1945年2月14日,用于军事用途。 后来因为计算机的优势和潜力巨大,计算机开始飞速发展,并产生了一个当时一直有效的定律:摩尔定律--当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍,性能也将提升一倍。 那么相应的,计算机就会变得越来越快,越来越小型化。

C 语言的基本数据类型

C 语言的基本数据类型 注:本文面向 C 语言初学者,如果你是熟手,那就不用看了。 有人问我,char、short、int、long、float、double 等这些关键字到底是什么意思,如果说他们是数据类型的话,那么为啥有这么多数据类型呢? 如果写了一句: int a; 那么执行的时候在内存中会有什么变化呢? 橡皮泥大家都玩过吧,一般你买橡皮泥的时候,店家会赠送一些模板。 上

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

Java 多线程的基本方式

Java 多线程的基本方式 基础实现两种方式: 通过实现Callable 接口方式(可得到返回值):

C++语法知识点合集:11.模板

文章目录 一、非类型模板参数1.非类型模板参数的基本形式2.指针作为非类型模板参数3.引用作为非类型模板参数4.非类型模板参数的限制和陷阱:5.几个问题 二、模板的特化1.概念2.函数模板特化3.类模板特化(1)全特化(2)偏特化(3)类模板特化应用示例 三、模板分离编译1.概念2.模板的分离编译 模版总结 一、非类型模板参数 模板参数分类类型形参与非类型形参 非类型模板