Lisp 中 /^c[ad]+r$/ 的 Ruby 实现
2016-03-12 本文已影响35人
Troubleshooting
我先简单说明一下我到底是想分享什么东西,对于没接触过 Lisp
的小伙伴很有必要,我只针对 car
、cdr
这两种序列操作简单说明一下,有兴趣的小伙伴去看 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