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

2016-03-12  本文已影响35人  Troubleshooting

我先简单说明一下我到底是想分享什么东西,对于没接触过 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
上一篇下一篇

猜你喜欢

热点阅读