Lisp 中 /^c[ad]+r$/ 的 Ruby 实现

我先简单说明一下我到底是想分享什么东西,对于没接触过 Lisp 的小伙伴很有必要,我只针对 carcdr 这两种序列操作简单说明一下,有兴趣的小伙伴去看 SICP,难免我讲的太片面

car z 取数组 z 中第一个元素, 就相当 z.first,这个没有什么特殊情况就这样理解就好
cdr z 取 z 中余下的元素,z.last 或 z[1 .. -1]
想要的效果是像下面这样:
cdar z 是这样 z[1 .. -1].first 也就是 z[1] 但也不见得是 z[1]
cddr z 就取两次剩余,相当与 z[1 .. -1][1 .. -1] 也就是 z[2 .. -1]
cadadadadaddadadadadadr, ......
caaaaaaaaaaaaaaar, ......
cdddddddddddaaaaaaaaaaaaar, ......

上述只是简单用 Ruby 数组表示序列和序对,有些事情没说的不是很清楚,再用 C 代码简单描述一下序对大概会长什么样子,因为源码我也没看过,下面只是我的理解,希望也能帮助你加深理解:

# 序对可以被定义成这样,其中 x, y 可指向任意类型
typedef struct {
    void *x;
    void *y;
} pair;

# 所谓序列,就是由上述序对构成的一个单向链表

我还是用 Ruby 吧不影响什么的,下面几个简单方法写出来帮助小伙伴再次理清思路

  def list *args; args; end

  def cons x, y; list x, y; end

  def pair? z; z.length == 2; end

  def car z; z.first; end

  def cdr z; pair?(z) ? z.last : z[1 .. -1]; end

最后,因为涉及函数式语言,应避用免循环实现,需要用是一个递归的 method_messing 实现 cadr, cdadr, caddaddr, ... 等诸如此类

  def method_missing method, *args
    return super unless method =~ /^c[ad]+r$/ and method.length > 3
    send "c#{method[2..-2]}r", send("c#{method[1]}r", *args)
  end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 第一部分Common Lisp介绍第1章 介绍一下Lisp你在学的时候觉得已经明白了,写的时候更加确信了解了,教别...
    geoeee阅读 3,021评论 5 8
  • 3.4 说说相等和内部表示 在Lisp中主要有5种相等断言,因为不是所有的对象被创建的时候都是相等意义上的相等。数...
    geoeee阅读 1,872评论 0 6
  • From:http://emacsist.com/10845 点 这里 查看更多 Emacs 相关推荐文章 或 最...
    海神之奏阅读 5,688评论 0 26
  • 一、异同对比选择1、Python和ruby的相同点: * 都强调语法简单,都具有更一般的表达方式。python是缩...
    沃伦盖茨阅读 4,202评论 2 24
  • 说明 函数式编程和面向对象编程可以说是编程的两大宗教,犹如编辑器之争一样,之间口角不断。我虽然靠着OOP的主力语言...
    lingyv阅读 1,717评论 1 14