热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么“无人问津”的Lisp可以这么狂?

一到周末,HelloWorld咖啡馆就比平时热闹得多,各种语言都来到这里,互相打探对方的最新特性,看看自己能不能借鉴一些。这

640?wx_fmt=jpeg

一到周末,Hello World 咖啡馆就比平时热闹得多, 各种语言都来到这里,互相打探对方的最新特性,看看自己能不能借鉴一些。 

这天晚上,由于Lisp的到来,咖啡馆的气氛显得格外热烈。 

Lisp

Lisp身穿一身时髦又奇异的括号服装, 和Clojure, Scala等几个函数式编程的忠实拥趸坐在一桌,谈笑风声,时不时挖苦一下隔壁的几个人,那里坐着以C语言为首的几个大佬。 

他悠闲地端起了一杯咖啡,悠悠地说道:“听说Java也用上了函数式编程? ”

Clojure道:“是啊,加上去没多久,好多人还没用熟呢!”

Lisp不屑地说道:“加上了也没用,不是我瞧不起他们,表达能力实在是太弱了!”

隔壁的C语言早就憋了一肚子火, 听到这句话,忍不住说道:“你嘚瑟什么呀,我知道你是基于Lambda演算的,但我们是基于图灵机的啊, 上世纪已经证明这图灵机和Lambda演算是等价的,所以我们的能力是一样的。 对了,你知不知道什么是图灵机,以及他的实现冯诺依曼架构啊?”

Lisp懒懒地说:“没兴趣了解,理论上计算能力是等价的,但并不代表在语言层面的表示一样,比如说,在我这里非常自然的函数式编程,在你们那里看起来就很别扭,是不是啊Java老弟?” 

Java有点不好意思,他很清楚,自己的函数式编程就是一个半吊子,所谓的Lambda表达式就是个接口实现而已。

(详情参见:《Lambda表达式有什么用?》)

Python出来解围:“ 我这里支持得很好啊,  我可以把函数当做参数进行传递,可以把函数当做返回值返回,还可以把函数保存到数据结构中!高阶函数map, reduce用起来也贼爽。”

Javascript接口道:“我也是啊!”

程序就是数据

Lisp 笑了一下,接着问道:“你们能在运行时创建新的函数吗?”

Java 看到展示自己的机会来了,马上接口道:“怎么不能? 在程序运行的时候,我可以通过操作Java字节码的方法,动态地生成函数和类,人们经常说的AOP就是这么玩的。”

Lisp很不屑:“还操纵字节码,还AOP,麻烦不麻烦!  低级不低级!丢人不丢人! ”

Java一脸愕然。

Lisp开始放大招: “你们能不能写个函数,把代码传递进去,然后对代码进行修改,然后返回新的代码?”

一个修改代码的函数?  代码可以在运行时修改? 这不是自虐吗?

“哈哈,这你们就不懂了吧, 凭什么数据结构可以变化,并且其中的数据可以修改,而程序却不能呢?在我这里,代码就是数据,代码可以在运行时被修改。”  Lisp很得意。

Javascript愤愤地说:“这有什么鸟用?”

Lisp看了看身边的Java ,又拿他开刀:“就拿你来举例吧, 你最早只有for 循环,没有for each 循环, 就是下面这样, 是不是被很多人骂啊?”

普通for 循环

for(int i=0;i}

for each 循环

for (Person p : perons){System.out.println(p);
}

Java无奈地点点头,Lisp说的是实话。

“这就是了,要想把这个新的语法给加上,那必须得在语言层面修改才行,对吧? 语言不支持,程序员骂也没用。 但是在我Lisp里就不一样了,根本就不用改动语言,一个程序员就能把这个新的语法给加上,并且新的for each 和 老的for 处于同等地位,相当于语言被扩展了。 ”

“不会吧,你怎么实现?” 

“自然是使用宏(Macro)了!”

“什么是宏? 和C老大的宏一样吗?” Java问道。

“C语言的宏就是编译期的文本替换而已,怎么能和我的宏相比? 给你说你也听不懂,通俗点说宏也是程序员写的代码, 运行时可以把代码传递给宏,然后宏可以修改这段代码,返回新的代码。 拿刚才的例子来说,假设for是个函数,程序员可以写一个for-each 的宏,在这个宏中,修改/扩展for函数的代码,实现for each的功能。”

C语言若有所思:“嗯,看来在你这里,程序也是数据啊,可以任意操作,果然厉害。如果把一段程序看成是抽象语法树(AST),那这个宏就相当于把AST做了修改,形成了新的AST。”

640?wx_fmt=png

Lisp心想,这老家伙还不赖, 已经Get到了。  

他说:“你们老是笑话我的括号多,但是你们不明白的是,这恰恰是我最大的优势,因为在我这里,数据和程序表示的方式是一致的,都是list,比如这一段简单的循环。”

(loop for x in '(1 2 3 4 5)do (print x) )

大家一看,果然如此,这代码(loop函数)是用括号括起来的一个List, 这数据(1 2 3 4 5)也是一个List。

Lisp说:“List的好处就是天然可以和AST对应,这就方便宏来操作了。”

640?wx_fmt=png

开发语言的语言

Javascript说:“我还是看不出有什么用?”

Lisp接着说:“正是由于程序可以当做数据来处理,程序员可以无限地扩充Lisp,把Lisp变成他们所在领域的语言,使用这个领域特定的语言来编程,那简直是如虎添翼,例如这个例子,通过扩展Lisp,   Lisp和SQL语言完美地融合了。 ”

(select [age] :from [employee] :where [> [salary] 50000])

“再比如说, 在座的各位大都支持面向对象编程,对我来说,在我这里实现OOP也是小菜一碟,比如Common Lisp中的CLOS,就是用宏实现的OOP操作集。”

大家都表示很好奇, Lisp就展示了几行代码:

定义一个叫Person的类

(defclass person ()((name :accessor person-name:initarg :name)(age :accessor person-age:initarg :age)))

创建一个person对象

(setf p (make-instance 'person :name "andy" :age 10))

访问对象的属性

(print (person-name p))

看到这里,大家都自愧弗如了, 这Lisp真有狂的资本啊。 

C 语言说到:“看来你Lisp是用来开发其他语言的语言啊!”

Lisp笑道:“这句话不错,在我这里,语言和程序之间的界限是非常模糊的。”

最后的反击

C语言问了最后一个问题:“既然你这么牛? 为什么用的人这么少?”

Lisp站起身来,叹了一口气:“有人说学起来门槛太高;有人说灵活与强大是一把双刃剑,每个人都能造属于自己的领域特定语言,让别人难以理解和维护;还有人说Lisp方言很多,社区分裂,没有统一的库让新手学习使用。 谁知道呢?”

说完Lisp便离开了,只留下一个满是括号的背影。

最新热门文章

为什么学习编程要从Web开始?

我是一个线程

我是一个Java Class

CPU阿甘

面向对象圣经

TCP/IP之大明邮差

负载均衡的原理

一个故事讲完HTTPs

编程语言的巅峰

Javascript:一个屌丝的逆袭

640?wx_fmt=jpeg


推荐阅读
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • 31.项目部署
    目录1一些概念1.1项目部署1.2WSGI1.3uWSGI1.4Nginx2安装环境与迁移项目2.1项目内容2.2项目配置2.2.1DEBUG2.2.2STAT ... [详细]
  • 初探PLC 的ST 语言转换成C++ 的方法
    自动控制软件绕不开ST(StructureText)语言。它是IEC61131-3标准中唯一的一个高级语言。目前,大多数PLC产品支持ST ... [详细]
  • 开发笔记:Python之路第一篇:初识Python
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Python之路第一篇:初识Python相关的知识,希望对你有一定的参考价值。Python简介& ... [详细]
  • 护墙_搭建LVS负载均衡NAT和DR模式
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了搭建LVS负载均衡NAT和DR模式相关的知识,希望对你有一定的参考价值。 ... [详细]
  • [翻译]微服务设计模式5. 服务发现服务端服务发现
    服务之间需要互相调用,在单体架构中,服务之间的互相调用直接通过编程语言层面的方法调用就搞定了。在传统的分布式应用的部署中,服务地 ... [详细]
  • 服务网关与流量网关
    一、为什么需要服务网关1、什么是服务网关传统的单体架构中只需要开放一个服务给客户端调用,但是微服务架构中是将一个系统拆分成多个微服务,如果没有网关& ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
    本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
  • c语言基础编写,c语言 基础
    本文目录一览:1、C语言如何编写?2、如何编写 ... [详细]
  • k8s+springboot+Eureka如何平滑上下线服务
    k8s+springboot+Eureka如何平滑上下线服务目录服务平滑上下线-k8s版本目录“上篇介绍了springboot+Euraka服务平滑上下线的方式,有部分小伙伴反馈k ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了SpringCloudRibbon部分源码相关的知识,希望对你有一定的参考价值。1:ribbon是提供通过servi ... [详细]
author-avatar
戴劳力士_484
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有