7 行代码 3 分钟:从零开始实现一门编程语言

本文最初发布于 Matt Might 的个人博客。

本文介绍了多种解释器实现。通过修改最后一个解释器,你应该可以快速测试关于编程语言的新想法。如果你希望有一种语法不一样的语言,就可以构建一个解析器,把 s-表达式转储。这样,你就可以干净利落地将语法设计与语义设计分开。

实现一门编程语言是任何程序员都不应该错过的经验;这个过程可以培养你对计算的深刻理解,而且很有趣。

本文直击本质,把整个过程归结为:一个面向函数式(但图灵等价)编程语言的 7 行解释器,而其实现只需要大约 3 分钟。

这个 7 行的解释器展示了许多解释器中都存在的可扩展架构——《计算机程序的结构与解释》中的 eval/apply 设计模式:

本文中总共有三种语言的实现:

  • 一个使用 Scheme 耗时 3 分钟实现的 7 行解释器;
  • 使用Racket重新实现;
  • 一个耗时“一下午”实现的 100 行解释器,实现了顶层绑定形式、显式递归、副作用、高阶函数等功能。如果想要实现一门功能更丰富的语言,那么最后一个解释器是一个不错的起点。

最容易实现的编程语言是一种极简的高阶函数式编程语言,名为λ演算(lambda calculus)。

实际上,λ演算是所有主要的函数式语言的核心——Haskell、Scheme 和 ML——但它也存在于 JavaScript、Python 和 Ruby 中。它甚至隐藏在 Java 中,不知道你是否知道在哪里可以找到它。

阿隆佐·丘奇在 1929 年开发了λ演算。

那时,它还不叫编程语言,因为当时没有计算机;没有什么东西可以“编程”。

它实际上只是一个用于函数推理的数学符号。幸运的是,阿隆佐·丘奇有一个博士生叫艾伦·图灵。

艾伦·图灵定义了图灵机,这成为通用计算机第一个公认的定义。

人们很快发现,λ演算和图灵机是等价的:任何能用λ演算描述的函数都能在图灵机上实现,而任何能在图灵机上实现的函数都能用λ演算描述。

值得注意的是,λ演算中只有三种表达式:变量引用、匿名函数和函数调用。

匿名函数的编写采用“lambda-dot”标记法,如下所示:

复制代码

该函数接受参数v ,返回值e 。如果用 JavaScript 编写,上述代码等价于:

复制代码

函数调用的写法是使两个表达式相邻:

复制代码

JavaScript(或其他任何语言)的写法如下:

复制代码

将参数原样返回的恒等函数写法如下:

复制代码

我们可以将恒等函数应用于恒等函数:

复制代码

(返回当然也是恒等函数。)下面这个程序更有意思一些:

复制代码

你能搞懂它做了什么吗?

乍一看,这门简单的语言似乎缺少递归和迭代,更不用说数值、布尔、条件、数据结构等其他东西。这种语言怎么可能是通用的呢?

λ演算达到图灵等价是通过两个最酷的编程黑科技实现的:Church 编码和 Y 组合子。

关于 Y 组合子,我已经写过一篇文章,关于Church编码,也写过一篇。不过,你不想读这些文章也没事,我只需一个程序就可以说服你,λ演算的功能远超你的预期:

复制代码

这个看上去无害的程序名为 Omega,如果你试图执行它,就发现它不会终止!(看看你能不能找出原因)。

下面是用 R5RS Scheme 耗时 3 分钟实现的一个 7 行λ演算解释器。从技术上讲(下文有解释),它是一个基于环境的指示型解释器。

复制代码

这段代码将从 stdin 读取一个程序,解析它,求值并打印结果。(去掉注释和空行,它只有 7 行)。Scheme 的read函数简化了词法分析和解析——只要你愿意生活在“平衡圆括号”(即s-表达式)的语法世界中。(如果不愿意,你就必须仔细研究解析中的词法分析;可以从我的一篇关于词法分析的文章入手)。在 Scheme 中,read从 stdin 中获取括号括起来的输入,并将其解析为一棵树。

evalapply 两个函数构成了解释器的核心。尽管是在 Scheme 中,但我们可以给予这些函数概念上的“签名”:

复制代码

eval函数接收一个表达式和一个环境然后转换为一个值。表达式可以是一个变量,一个 lambda 项或一个应用程序。环境是一个从变量到值的映射,用来定义一个开项的自由变量。(开项是一个变量的非绑定出现。)例如,考虑一下表达式(λ x . z)。这个项是开放的,因为我们不知道z是什么。

由于用的是 R5RS Scheme,我们可以使用关联列表来定义环境。

闭包是一个函数的编码,它将一个(可能是开放的)lambda 表达式与一个环境配对,以定义其自由变量。换句话说,一个闭包封闭了一个开项。

Racket是 Scheme 的一种方言,它功能齐备,可以把事情做好。Racket 提供了一个可以清理解释器的匹配结构,如下所示:

复制代码

这个代码多点,但更简洁,更容易理解。

λ演算是一门很小的语言。即便如此,其解释器的 eval/apply 设计也可以扩展到更大的语言。例如,用大约 100 行代码,我们可以为一个相当大的 Scheme 子集实现一个解释器。

考虑一种具有各种表达形式的语言:

  1. 变量引用,如:xfoosave-file
  2. 数值和布尔常量,如:3003.14#f
  3. 基本操作,如:+<=
  4. 条件:(if condition if-true if-false)
  5. 变量绑定:(let ((var value) …) body-expr)
  6. 递归绑定:(letrec ((var value) …) body-expr)
  7. 变量可变:(set! var value)
  8. 定序:(begin do-this then-this)。现在,为这门语言添加 3 个顶层形式:
  9. 函数定义:(define (proc-name var …) expr)
  10. 全局定义:(define var expr)
  11. 顶层表达式:expr。下面是完整的解释器,其中包括测试工具和测试用例:

复制代码

下载源代码,请点击https://matt.might.net/articles/implementing-a-programming-language/minilang.rkt?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhY2Nlc3NfcmVzb3VyY2UiLCJleHAiOjE2NTU0NTMzMzAsImZpbGVHVUlEIjoibG9xZVcyRXl2d0hkSkxBbiIsImlhdCI6MTY1NTQ1MzAzMCwidXNlcklkIjoyMDQxOTA5MH0.Nv5UyUdCUJNT7c0kIaPSE0g0f4k9Ed26rLl2Bu5RpG4

通过修改最后一个解释器,你应该可以快速测试关于编程语言的新想法。

如果你希望有一种语法不一样的语言,就可以构建一个解析器,把 s-表达式转储。这样,你就可以干净利落地将语法设计与语义设计分开。

查看英文原文:

https://matt.might.net/articles/implementing-a-programming-language?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhY2Nlc3NfcmVzb3VyY2UiLCJleHAiOjE2NTU0NTMzMzAsImZpbGVHVUlEIjoibG9xZVcyRXl2d0hkSkxBbiIsImlhdCI6MTY1NTQ1MzAzMCwidXNlcklkIjoyMDQxOTA5MH0.Nv5UyUdCUJNT7c0kIaPSE0g0f4k9Ed26rLl2Bu5RpG4

编程高手最爱的编程入门教程,学会你就是高手了!

开发以及编程人员,一般薪资比较高。但是这个行业处于快速的发展中,计算机人才的需求供不应求。因此,很多人也想步入计算机行业。但是要想自学编程,不是一件容易的事情。单靠自己一个人,简直没方向,像无头苍蝇一样乱撞。别着急,W3Cschool小师妹为大家收集了免费的编程入门教程。这些教程,可以让你一步一步的学会编程。

1.学习HTML

HTML指的是文本标签语言,它也是一种书写网页代码的规范和标准。学习HTML说难也不难,说容易也不简单。其实就是要掌握好方法,下面W3Cschool小师妹为大家精选的HTML教程,教你如何利用HTML创建站点。主要包括HTML实例、HTML标题、段落、媒体等,可以去http://www.w3cschool.cn/html/看一下。

2.HTML5教程

HTML5非常火,很多公司都要求开发者会HTML5。HTML5是下一代的HTML,目前仍然处于没有完善中。W3Cschool小师妹为大家收集的HTML5教程,你可以了解到HTML5拥有哪些新特性。这部分内容,主要包括HTML5 浏览器支持、HTML5 新元素、HTML5 Canvas、HTML5 内联 SVG、HTML5 拖放、HTML5 地理定位等。

3.CSS教程

CSS是一种计算机语言,主要用来表现XML亦或者HTML的一种文件样式。W3Cschool为大家精选的CSS教程,你可以学习到怎么样使用CSS,同时对整个站点的布局以及样式进行布局。

4.CSS3教程

CSS3 是 CSS 的进阶版,在此本教程中,你可可以学到CSS3 边框、CSS3 圆角、CSS3 背景、CSS3 渐变、CSS3 文本效果等知识。欲知详情,请移步http://www.w3cschool.cn/css3/。

5.javascript教程

JavaScript是世界上最流行的脚本语言,一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。JavaScript运用在移动电话、平板电脑、PC等处。

6.正则表达式

正则表达式是计算机科学的一个概念,是对字符串操作的一种逻辑公式,也叫常规表示法、正规表示法。W3Cschool小师妹为大家收集的正则表达式教程,主要涵盖语法、元字符、运算符优先级、匹配规则等。

自学编程,如果有一本好的编程教程,无异于良师。上面W3Cschool小师妹为大家精选的编程自学教程,全部在http://www.w3cschool.cn这边,希望大家喜欢。

公众号:w3cschoolcn

初学者不知道怎么学编程?那么你一定要收藏这篇文章

众所周知在快速发展的信息时代,程序员是极具优势的工作,不仅很少被社会琐事烦扰,还能拥有极高报酬。可是作为一个零基础的初学者该怎么成为一名合格的程序员呢?那么下面就让我分析一下初学者该怎么学习编程。

要当程序员,肯定是要从学习一门编程语言开始。这是HelloGitHub给出的2022年5月编程语言排行榜:

可以从这个排行榜中清楚地看到哪些是热门语言,我整理了一下对于各种语言的看法,但是具体怎么选择就看你自己的需求啦:

  1. Python:它很适合初学者,简单易学,并且和人工智能关系密切。目前主要应用于web开发、应用开发、大数据、数据挖掘、科学计算、机器学习、人工智能、运维、自然语言处理等等。
  1. Java:相对于C也是比较简单的语言,不过它的学习难度肯定比Python大,在这三个语言中难度中等,、目前主要应用于安卓和 IOS 的应用开发、视频游戏开发、桌面GUI、软件开发等等。
  1. C:难度最大,主要应用在操作系统、嵌入式领域和服务器领域。应用范围广,薪资待遇高。C++ 是 C 语言的一个超集,既有指针又有对象使它成为最复杂的语言。几乎所有现代编程语言都由C/C++发展而来,因此了解C/C++非常有利于快速掌握其他各类编程语言;
  1. JavaScript: JavaScript 是一种动态类型、弱类型、基于原型的直译式脚本语言,也是使用频率最高的给 HTML 网页增加动态功能的语言。作为脚本语言,JavaScript 可立即运行而无需等待服务器响应,速度非常出色,并且它是动态类型语言,学习难度低。

这几个各有各的特色,但是如果你想入门当程序员,那我建议你从Python和Java中选,这两种语言相较于C来说,更容易上手。

作为初学者,当你把编程语言学到一定程度后,接下来就是编程的通用技能了:基本的算法和数据结构。

你可能会说,你以后想找的工作很简单,和算法这一块儿关系并不大,有基本的知识就够了;但要知道的是,这东西就好比地基,你之后的一切工作都将在这基础上开展,如果不会以后进入工作了将花费大量的时间精力和金钱在上面。

在我看来,这些是必须要掌握的:

10个算法:二分查找、递归、排序、搜索、哈希算法、分治算法、回溯算法、贪心算法、动态规划、字符串匹配算法。

10个数据结构:栈、数组、链表、队列、堆、跳表、图、Trie 树、散列表、二叉树;

千万不要小瞧这它们,每一个展开了去细学,怎么都得要一年半载;想想办法把这些吃透,起码以后再看见这些问题不用翻书,然后你就可以进一步向更深的层次进发,去思考这些问题:

编程框架是如何运转起来的?

主流的编程框架和设计模式存在怎样的共通模式呢?

List、Hash、key各自的应用场景和共通之处?

……

每一个问题都是一座大山,当你想明白并且拿出可行的解决方案,你的技术相比以往就会提升一个Level。

“实践出真知”,这话放在编程的学习中,显得尤为合适。

网上有一句比较流行的话,“我的眼睛和大脑都会了,但是手不会。”学习编程的过程中也容易出现这些问题;可能你通过看书、看视频突然get到了某一个点,但是并没有去实操,在不久后重新遇到相关的问题,全部忘记也是正常的。

所以,寻找实操性较高的个人项目,提升阅读和编译速度,是学习编程的不二之选。GitHub上有几个有趣的项目,可以参考一下:

  1. lllyasviel/style2paints 这是一个能够根据用户自定义的颜色给线稿上色的工具。在这里,以ABCD这种格式呈现一些结果。你只需要上传你的的草图,选择一种样式,然后放置光源。就可以实现AI上色当结果在没有任何人为颜色校正的情况下立即获得时,我们将此结果视为全自动结果。当结果需要一些颜色校正时,人类可以很容易地在画布上放置一些颜色提示,以指导AI着色过程。
  1. seq2seq-couplet 这是一个使用 seq2seq 模型来进行对联(对对联)的项目。
  1. MisterBooo/LeetCodeAnimation 为了帮助大家更好的入门学习算法,经过半年的积累,创作者给大家整理了《剑指 Offer》系列的四十道题目,都是算法面试的高频题目,每一道题目都提供详细的分析、精美的配图、易于理解的动画视频,适合那些第一次刷题的同学,当然,也适合重复刷题的老手再次学习巩固基础。

这篇文章就介绍到这里,希望对初学者能有所帮助,欢迎点赞分享

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。