当前位置: 首页 > news >正文

用 C 语言开发一门编程语言 — 函数库的设计与实现

目录

文章目录

  • 目录
  • 前言
  • 前文列表
  • 基础功能演示
    • 数字运算
    • 变量与代数运算
    • 列表处理
    • Lambda 函数
    • 条件分支
    • 字符串
    • 源文件加载
  • 函数库
    • 列表处理函数库
    • 条件分支函数库
    • 数学库

前言

通过开发一门类 Lisp 的编程语言来理解编程语言的设计思想,本实践来自著名的《Build Your Own Lisp》。

  • 代码实现:https://github.com/JmilkFan/Lispy

前文列表

《用 C 语言开发一门编程语言 — 交互式解析器》
《用 C 语言开发一门编程语言 — 语法解析器运行原理》
《用 C 语言开发一门编程语言 — 波兰表达式解析器》
《用 C 语言开发一门编程语言 — 表达式存储器》
《用 C 语言开发一门编程语言 — 符号表达式解析器》
《用 C 语言开发一门编程语言 — 引用表达式解析器》
《用 C 语言开发一门编程语言 — 变量的设计与实现》
《用 C 语言开发一门编程语言 — 基于 Lambda 表达式的函数设计与实现》
《用 C 语言开发一门编程语言 — 条件分支的设计与实现》
《用 C 语言开发一门编程语言 — 字符串的设计与实现》

基础功能演示

目前为止,我们开发的编程语言已经拥有了以下功能:

  1. 交互式解析器界面;
  2. MPC 语法解析器;
  3. 基于波兰表达式的数字运算;
  4. 基于符号表达式的代数运算;
  5. 基于引用表达式的变量;
  6. 基于 Lambda 表达式的函数;
  7. 条件分支逻辑控制语句;
  8. 文件加载;
  9. 等等。

在本文中,我们将完整的演示上述技术功能,并尝试通过预定义一些常用的函数库来辅助编程。

数字运算

lispy> + 4 5  // 4+5
9
lispy> - 8 3  // 8-3
5
lispy> * 6 2  // 6 * 2
12
lispy> / 10 5  // 10/5
2
lispy> / 10 0  // 10/0
Division By Zero!
lispy> - (* 10 10) (+ 1 1 1)  // (10*10) - (1+1+1)
97

变量与代数运算

lispy> def {x} 1
()
lispy> + x 1
2
lispy> def {y} 2
()
lispy> + x y
3
lispy> def {a b} 2 3
()
lispy> + a b
5
lispy> + x (* a b) y  // x + (a * b) + y
9
lispy> def {arglist} {a b c d}
()
lispy> def arglist 1 2 3 4
()
lispy> list a b c d
{1 2 3 4}

列表处理

lispy> def { l1 } {1 2 3}
()
lispy> def { l2 } {4 5 6}
()
lispy> head l1
{1}
lispy> tail l1
{2 3}
lispy> join l1 l2
{1 2 3 4 5 6}
lispy> list l1 l1
{{1 2 3} {1 2 3}}
lispy> eval {+ 1 2 3}
6

Lambda 函数

lispy>  def {add-mul} (\ {x y} {+ x (* x y)})
()
lispy> add-mul 10 20
210
lispy> add-mul 30 40
1230
lispy> def {add-mul-ten} (add-mul 10)
()
lispy> add-mul-ten 50
510

条件分支

lispy> def {x y} 100 200
()
lispy> if (== x y) {+ x y} {- x y}
-100
lispy> if (< x y) {+ x y} {- x y}
300

字符串

lispy> print "Hello World!"
"Hello World!"
()
lispy> error "This is an error!"
This is an error!

源文件加载

$ cat hello.lspy
(print "hello world.")$ main hello.lspy
"hello world."

函数库

列表处理函数库

  • list.lspylib
; 空类型
(def {nil} {}); 布尔类型
(def {true} 1)
(def {false} 0); 函数定义 Lambda 表达式
(def {fun} (\ {f b} {def (head f) (\ (tail f) b)
})); 取列表中的第一、二、三项
(fun {fst l} { eval (head l) })
(fun {snd l} { eval (head (tail l)) })
(fun {trd l} { eval (head (tail (tail l))) }); 获取列表长度
(fun {len l} {if (== l nil){0}{+ 1 (len (tail l))}
}); 取列表中的第 n 项
(fun {nth n l} {if (== n 0){fst l}{nth (- n 1) (tail l)}
}); 取列表中的最后一项
(fun {last l} {nth (- (len l) 1) l}); 取列表中的前 n 项
(fun {take n l} {if (== n 0){nil}{join (head l) (take (- n 1) (tail l))}
}); 删除列表中的前 n 项
(fun {drop n l} {if (== n 0){l}{drop (- n 1) (tail l)}
}); 从第 n 项分裂列表
(fun {split n l} {list (take n l) (drop n l)}); 取元素的 idx
(fun {elem x l} {if (== l nil){false}{if (== x (fst l)) {true} {elem x (tail l)}}
}); Map 函数:所有列表元素执行相同的操作
(fun {map f l} {if (== l nil){nil}{join (list (f (fst l))) (map f (tail l))}
}); Filter 函数:根据过滤条件进行元素过滤
(fun {filter f l} {if (== l nil){nil}{join (if (f (fst l)) {head l} {nil}) (filter f (tail l))}
}); Fold Left 函数:向左折叠逐一执行指定函数操作
(fun {foldl f z l} {if (== l nil){z}{foldl f (f z (fst l)) (tail l)}
}); 向左折叠求和
(fun {sum l} {foldl + 0 l})
; 向左折叠求积
(fun {product l} {foldl * 1 l})

应用:列表处理。

lispy> load "./samples/list.lspylib"
()
lispy> def {l1} {1 2 3 4 5 6}
()
lispy> len l1
6
lispy> nth 2 l1
3
lispy> last l1
6
lispy> take 3 l1
{1 2 3}
lispy> def {l2} (drop 4 l1)
()
lispy> l2
{5 6}
lispy> split 5 l1
{{1 2 3 4 5} {6}}
lispy> elem 1 l1
1
lispy> elem 7 l1
0
lispy> map (\ {x} {+ x 10}) {5 2 11}  // 所有元素的数值 +10
{15 12 21}
lispy> filter (\ {x} {> x 2}) {5 2 11 -7 8 1}  // 过滤出 >2 的元素
{5 11 8}
lispy> sum l1      // 求和
21
lispy> product l1  // 求积
720

条件分支函数库

  • condition.lspylib
; 空类型
(def {nil} {}); 布尔类型
(def {true} 1)
(def {false} 0); 函数定义 Lambda 表达式
(def {fun} (\ {f b} {def (head f) (\ (tail f) b)
})); 取列表中的第一、二、三项
(fun {fst l} { eval (head l) })
(fun {snd l} { eval (head (tail l)) })
(fun {trd l} { eval (head (tail (tail l))) }); Unpack List for Function
(fun {unpack f l} {eval (join (list f) l)
})
; Pack List for Function
(fun {pack f & xs} {f xs}); switch 关键字
(fun {switch & cs} {if (== cs nil){error "No Selection Found"}{if (fst (fst cs)) {snd (fst cs)} {unpack switch (tail cs)}}
}); default 关键字
(def {default} true); case 关键字
(fun {case x & cs} {if (== cs nil){error "No Case Found"}{if (== x (fst (fst cs))) {snd (fst cs)} {unpack case (join (list x) (tail cs))}}
}); 条件选择月份后缀函数
(fun {month-day-suffix i} {switch{(== i 0)  "st"}{(== i 1)  "nd"}{(== i 3)  "rd"}{default   "th"}
}); 条件选择星期几函数
(fun {day-name x} {case x{0 "Monday"}{1 "Tuesday"}{2 "Wednesday"}{3 "Thursday"}{4 "Friday"}{5 "Saturday"}{6 "Sunday"}
})
  • 应用:switch/case 语句。
lispy> load "./samples/condition.lspylib"
()
lispy> month-day-suffix 1
"nd"
lispy> month-day-suffix 2
"th"
lispy> day-name 0
"Monday"
lispy> day-name 1
"Tuesday"

数学库

  • fibonacci.lspylib
; 空类型
(def {nil} {}); 布尔类型
(def {true} 1)
(def {false} 0); 函数定义 Lambda 表达式
(def {fun} (\ {f b} {def (head f) (\ (tail f) b)
})); 取列表中的第一、二、三项
(fun {fst l} { eval (head l) })
(fun {snd l} { eval (head (tail l)) })
(fun {trd l} { eval (head (tail (tail l))) }); Unpack List for Function
(fun {unpack f l} {eval (join (list f) l)
})
; Pack List for Function
(fun {pack f & xs} {f xs}); switch 关键字
(fun {switch & cs} {if (== cs nil){error "No Selection Found"}{if (fst (fst cs)) {snd (fst cs)} {unpack switch (tail cs)}}
}); default 关键字
(def {default} true); Fibonacci
(fun {fib n} {switch{ (== n 0) 0 }{ (== n 1) 1 }{ default (+ (fib (- n 1)) (fib (- n 2))) }
})
  • 应用:
lispy> load "./samples/fibonacci.lspylib"
()
lispy>
()
lispy> fib 10
55
lispy> fib 20
6765

相关文章:

用 C 语言开发一门编程语言 — 函数库的设计与实现

目录 文章目录目录前言前文列表基础功能演示数字运算变量与代数运算列表处理Lambda 函数条件分支字符串源文件加载函数库列表处理函数库条件分支函数库数学库前言 通过开发一门类 Lisp 的编程语言来理解编程语言的设计思想&#xff0c;本实践来自著名的《Build Your Own Lisp》…...

网络层IP协议与数据链路层以太网协议

文章目录一、IP协议IP地址地址管理路由选择DNS二、以太网协议以太网帧MTU一、IP协议 IP协议是我们网络层的代表协议&#xff0c;今天我们就来一起学习一下吧&#xff0c;我们这里介绍的主要是IPv4协议。 版本&#xff1a;指定IP协议的版本&#xff0c;版本的取值只有4&#x…...

JDK动态代理详解

1.什么是动态代理 可能很多小伙伴首次接触动态代理这个名词的时候&#xff0c;或者是在面试过程中被问到动态代理的时候&#xff0c;不能很好的描述出来&#xff0c;动态代理到底是个什么高大上的技术。不方&#xff0c;其实动态代理的使用非常广泛&#xff0c;例如我们平常使用…...

实时的软件生成 —— Prompt 编程打通低代码的最后一公里?

PS&#xff1a;这也是一篇畅想&#xff0c;虽然经过了一番试验&#xff0c;依旧有一些不足&#xff0c;但是大体上站得住脚。传统的软件生成方式需要程序员编写大量的代码&#xff0c;然后进行测试、发布等一系列繁琐的流程。而实时生成技术则是借助人工智能技术&#xff0c;让…...

互联网工程师 1480 道 Java 面试题及答案整理 ( 2023 年 整理版)

最近很多粉丝朋友私信我说&#xff1a;熬过了去年的寒冬却没熬过现在的内卷&#xff1b;打开 Boss 直拒一排已读不回&#xff0c;回的基本都是外包&#xff0c;薪资还给的不高&#xff0c;对技术水平要求也远超从前&#xff1b;感觉 Java 一个初中级岗位有上千人同时竞争&#…...

Spark开发

第一步&#xff1a;创建RDD Spark提供三种创建RDD方式&#xff1a;** 集合、本地文件、HDFS文件** 使用程序中的集合创建RDD&#xff0c;主要用于进行测试&#xff0c;可以在实际部署到集群运行之前&#xff0c;自己使用集合构造一些测试数据&#xff0c;来测试后面的spark应…...

Tornado异步框架

简介&#xff1a; tornado是Python的web框架。tornado和主流的web服务器框架有明显的区别&#xff1a;它是非阻塞式服务器&#xff0c;而且速度非常快&#xff0c;得力于其非阻塞的方式和epoll的运用tornado可以每秒处理数以千计的连接&#xff08;号称&#xff09; 基本配置 …...

openpnp - error - 吸嘴没下降到板子上, 就将元件松开

文章目录openpnp - error - 吸嘴没下降到板子上, 就将元件松开概述笔记ENDopenpnp - error - 吸嘴没下降到板子上, 就将元件松开 概述 以前用过国内一家openpnp厂家出的设备, 他们家的openpnp是自己改过的. 贴片流程已经走过一遍. 这次还是按照以前记录的笔记, 按照国内那家的…...

【Java】yyyy-MM-dd HH:mm:ss 时间格式 时间戳 全面解读超详细

时间格式 时间格式(协议)描述gg时期或纪元。y不包含纪元的年份。不具有前导零。yy不包含纪元的年份。具有前导零。yyyy包含纪元的四位数的年份。M月份数字。一位数的月份没有前导零。MM月份数字。一位数的月份有一个前导零。MMM月份的缩写名称&#xff0c;在AbbreviatedMonthN…...

快鲸SCRM发布口腔企业私域运营解决方案

口腔企业普遍面临着以下几方面运营痛点问题 1、获客成本居高不下&#xff0c;恶性竞争严重 2、管理系统落后&#xff0c;人员流失严重 3、客户顾虑多、决策时间长 4、老客户易流失&#xff0c;粘性差 以上这些痛点&#xff0c;不得不倒逼口腔企业向精细化运营客户迈进。 …...

Verilog实现组合逻辑电路

在verilog 中可以实现的数字电路主要分为两类----组合逻辑电路和时序逻辑电路。组合逻辑电路比较简单&#xff0c;仅由基本逻辑门组成---如与门、或门和非门等。当电路的输入发生变化时&#xff0c;输出几乎&#xff08;信号在电路中传递时会有一小段延迟&#xff09;立即就发生…...

2023前端菜鸟笔试血泪史html5-one--找到工作前都更新

1.说说对html语义化的理解 什么的HTML语义化&#xff0c;顾名思义&#xff0c;HTML语义化就是可以不通过了解HTML的内容&#xff0c;就可以知道这个部分所代表的的意义。 HTML语义化的意义&#xff1a;在使用HTML标签构建页面时&#xff0c;避免大篇幅的使用无语义的标签。 …...

蓝牙调试工具集合汇总

BLE 该部分主要分享一下常用的蓝牙调试工具&#xff0c;方便后续蓝牙抓包及分析。 目录 1 hciconfig 2 hcitool 3 hcidump 4 hciattach 5 btmon 6 bluetoothd 7 bluetoothctl 1 hciconfig 工具介绍&#xff1a;hciconfig&#xff0c;HCI 设备配置工具 命令格式&…...

Java 获取文件后缀名【一文总结所有方法】

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

UML常见图的总结

一、概述 UML&#xff1a;Unified Modeling Language&#xff0c;统一建模语言&#xff0c;支持从需求分析开始的软件开发的全过程。是一个支持模型化和软件系统开发的图形化语言、为软件开发的所有阶段提供模型化和可视化支持&#xff0c;包括由需求分析到规格&#xff0c;到…...

WebRTC系列-工具系列之音频相关工具

文章目录 1. audio_util数据格式转换类2. WavFile文件读写类2.1 读取wav文件2.2 写入wav文件这篇文章主要介绍WebRTC中一些音频工具这些,大部分都在 common_audio目录下,这个文件夹下提供音频的大量算法,包括sinc重采样算法,音频数据格式的转换:例如 float转int16_t格式等…...

7 线性回归及Python实现

1 统计指标 随机变量XXX的理论平均值称为期望: μE(X)\mu E(X)μE(X)但现实中通常不知道μ\muμ, 因此使用已知样本来获取均值 X‾1n∑i1nXi.\overline{X} \frac{1}{n} \sum_{i 1}^n X_i. Xn1​i1∑n​Xi​.方差variance定义为&#xff1a; σ2E(∣X−μ∣2).\sigma^2 E(|…...

适合小团队协作、任务管理、计划和进度跟踪的项目任务管理工具有哪些?

适合小团队协作、任务管理、计划和进度跟踪的项目任务管理工具有哪些? 大家可以参考这个模板&#xff1a;http://s.fanruan.com/irhj8管理项目归根结底在管理人、物&#xff0c;扩展来说便是&#xff1a; 人&#xff1a;员工能力、组织机制&#xff1b; 物&#xff1a;项目内…...

从100%进口到自主可控,从600块降到10块,中科院攻克重要芯片

前言 2月28日&#xff0c;“20多位中科院专家把芯片价格打到10块”冲上微博热搜&#xff0c;据河南省官媒大象新闻报道&#xff0c;热搜中提到的中科院专家所在企业为全球最大的PLC分路器芯片制造商仕佳光子&#xff0c;坐落于河南鹤壁。 为实现芯片技术自主可控自立自强&#…...

关于git的一些基本点总结

1.什么是git? git是一个常用的分布式版本管理工具。 2.git 的常用命令: clone&#xff08;克隆&#xff09;: 从远程仓库中克隆代码到本地仓库 checkout &#xff08;检出&#xff09;:从本地仓库中检出一个仓库分支然后进行修订 add&#xff08;添加&#xff09;: 在提交前…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...

6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础

第三周 Day 3 &#x1f3af; 今日目标 理解类&#xff08;class&#xff09;和对象&#xff08;object&#xff09;的关系学会定义类的属性、方法和构造函数&#xff08;init&#xff09;掌握对象的创建与使用初识封装、继承和多态的基本概念&#xff08;预告&#xff09; &a…...