`
deepinmind
  • 浏览: 450845 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
1dc14e59-7bdf-33ab-841a-02d087aed982
Java函数式编程
浏览量:41555
社区版块
存档分类
最新评论

其实你已经在使用Lisp语法了

阅读更多
UNIX开发人员(以下简称UD, Unix Developer):我再也不会碰LISP了。太可怕了!

我:为什么这么说?

UD:它的语法!那个波兰式的前缀语法看得眼睛都花了,也就只有它在用了。你看看这些个括号!

我:好吧,但很多人认为这个可读性很强,尽管他们也承认是得花点时间才能习惯它。但我觉得你错了。很多人其实每天都在使用Lisp语法。。。

UD:据我所知,没人像你说的这样。

我:。。他们可能自己都没意识到这个。事实上,我认为你也在使用它。

UD:等等,你说什么?!

我:你用的这个特殊的Lisp语法的变种又叫做Bourne Shell。

UD:这我可听不明白了。shell和Lisp有毛关系?

我:你看下shell里面,你先输入程序名,然后是参数,它们用空格为分隔开。Lisp里面也是这样的,只不过你放了一个左括号在前面,最后又加上了一个右括号。

Shell: run-something arg1 arg2 arg3

Lisp: (run-something arg1 arg2 arg3)

UD: 我还是没感觉有什么像的。

我:现在你需要一种机制将表达式组合起来——也就是将一个表达式的输出作为另一个表达式的输入。在Lisp里面,你需要嵌套列表了。那么在shell里呢?

UD:`

我:对的。或者是$(),它的好处是更容易嵌套了。我们来试一下算术运算。你在shell里是怎么进行数学运算的?

UD: expr。或者shell内建的let,比如这样:


$ let x='2*((10+4)/7)'; echo $x
4
 


我:这个可能有点不太符合UNIX的精神了——一个程序应当只做一件事情——我们应该有一个程序来做加法,一个做减法,还有的分别做乘法和除法。

用C来写一个的话很简单:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv) {
  int mode = -1, cnt = argc - 1, val, i;
  char **args = argv + 1;
  switch (argv[0][strlen(argv[0]) - 1]) {
    case '+': mode = 0; break;
    case '-': mode = 1; break;
    case 'x': mode = 2; break;
    case 'd': mode = 3; break;
  }
  if (mode == -1) {
    fprintf(stderr, "invalid math operation\n");
    return 1;
  }
  if ((mode == 1 || mode == 3) && !cnt) {
    fprintf(stderr, "%s requires at least one arg\n", argv[0]);
    return 1;
  }
  switch (mode) {
    case 0: val = 0; break;
    case 2: val = 1; break;
    default: val = atoi(*args++); cnt--; break;
  }
  while (cnt--) {
    switch (mode) {
      case 0: val += atoi(*args++); break;
      case 1: val -= atoi(*args++); break;
      case 2: val *= atoi(*args++); break;
      case 3: val /= atoi(*args++); break;
    }
  }
  printf("%d\n", val);
  return 0;
}
 


这个程序是根据名字的最后一个字符进行分发的,因此你可以将它编译成+,-, x和d(这里乘法和除法用的名字不太常用,因为这是合法字符也省得转义了)

现在看吧:


$ x 2 $(d $(+ 10 4) 7)
4
 


UD: 好吧,这真的看真来很像Lisp了。

我:是的,但这就是shell。我们的两个基本原则——程序名在前,$()用来组合操作——这样就能明确区分出求值的顺序,也不需要做额外的解析了,因为shell已经提供了这样的功能。

UD:那么shell也是Lisp的一种吗?

我:不算是。shell是字符串类型的:程序接收文本参数,输出的也是文本的结果。要想成为Lisp中的一员,它还得有一个组合类型:列表或者cons单元,你可以用它来构建列表。然后,你还需要能够用数据结构来表示代码,可以编写程序来对代码进行转化。

不过,shell的语法中蕴含着Lisp之道。



我知道我这里漏掉了许多细节,比如shell的重定向,命令替换,子进程,程序除了命令行参数外还有标准准入,以及管道,等等——这些都使得shell看起来不那么像Lisp。不过我认为这是向大家介绍Lisp语法的一个很有趣的方式。



原创文章转载请注明出处:http://it.deepinmind.com

英文原文链接
2
1
分享到:
评论

相关推荐

    lisp语言陈光喜2005

    通过对这些知识点的学习,读者能够对Lisp语言有一个全面的认识,并能够掌握其基础语法和编程技巧。Lisp虽然看似简单,但其实内涵丰富,对于想要深入了解函数式编程的人来说,是一门值得学习的语言。

    cpp-FlycheckGNUEmacs的快速语法检查

    它能在编写代码的同时快速检测出语法错误、类型错误和风格问题,帮助程序员在编码阶段就发现并修复问题,避免了在编译或运行时才暴露错误。 **Flycheck的基本工作原理** Flycheck的核心功能是它能够在你键入代码的...

    聊聊Java平台上的非Java语言共3页.pdf.zip

    在Java平台上,尽管Java语言是主要的开发工具,但其实并不仅限于Java,还有许多其他编程语言可以在Java虚拟机(JVM)上运行。这些语言通常被称为“JVM语言”,因为它们编译成字节码,可以在Java虚拟机上执行,从而...

    A_Tour_of_Scheme_in_Gambit

    - **括号的重要性**:由于Scheme是Lisp家族的一员,因此确实使用了大量的括号。括号用于表示列表(lists),而列表是Scheme数据结构的基础。括号不仅用于定义函数调用,还用于表示表达式。 - **避免混淆**:虽然括号多...

    Ruby语言入门教程V1.0

    Ruby作为一种动态、面向对象的解释型语言,在21世纪初逐渐崭露头角,并因其简洁易读的语法和强大的功能受到了广大开发者的喜爱。 ##### 1.2 编程其实很容易 编程并非遥不可及的技术,只要有正确的方法和足够的练习...

    Linux操作系统基础教程

    者的使用活动基本不受限制(只要你不将它用于商业目的),而不必像使用微软产品是那样, 2需要为购满许可证付出高价还要受到系统安装数量的限制。我在讲义的最后面附有 GPL 的 非官方中文译稿。目前 Linux 中国的...

    lt-user-plugin:我的 Light Table 用户插件 - 我所有设置和调整的新家

    1. **插件开发**:在 Light Table 中,你可以使用 ClojureScript 来编写插件。这个 "lt-user-plugin" 可能是一个模板或者示例,指导用户如何创建自己的定制插件,以实现特定的编辑器功能,如代码高亮、自动完成、...

    howtoSC3

    《SuperCollider学习指南:howtoSC3》 SuperCollider是一款强大的实时音频合成和编程语言,专为音乐家...不断实践和探索,你将能够利用SuperCollider创造出独特的音频体验,并在音乐创作和实验声音艺术领域大展拳脚。

    Data-Structure-in-Scheme:在方案中构建数据结构

    Scheme是一种功能强大的Lisp方言,以其简洁的语法和强大的元编程能力而闻名。在Scheme中,理解并熟练掌握数据结构是编程的基础,也是深入探索函数式编程世界的钥匙。本文将详细探讨在Scheme中构建常见数据结构的方法...

    dotemacs:我的个人.emacs配置

    在描述中提到的“黑暗主题”和“轻主题”,其实是Emacs中的颜色主题。厄运(Doom)是一个广受欢迎的Emacs框架,它提供了许多预设的主题,如Kong雀和北光。这些主题通过改变字体颜色、背景色和高亮色,为用户提供不同...

    gerbil-simsub:用Gerbil编写的pubsub协议及其模拟器

    本文将深入探讨Gerbil-Simsub的核心概念、设计原则以及其实现细节。 首先,我们来了解一下什么是Gerbil。Gerbil是一种基于Lisp方言的编程语言,它继承了Scheme语言的简洁性和表达力,同时针对性能和现代编程需求...

Global site tag (gtag.js) - Google Analytics