2009-10-05 22 views
20

是否有紅寶石等同於lisp car,cdr和cons函數?對於那些不熟悉口齒不清,這是我從紅寶石想:有汽車,司機,和利弊紅寶石等值?

[1,2,3].car => 1 
[1,2,3].cdr => [2,3] 
[2,3].cons(1) => [1,2,3] 

(在LISP):

(car '(1 2 3)) => 1 
(cdr '(1 2 3)) => (2 3) 
(cons 1 '(2 3)) => (1 2 3) 

回答

28

Ruby的數組不實現單鏈表,所以它不是作爲有用的汽車和CDR之類的東西。

如果你真的想,你可以做

[1,2,3][0]  => 1 
[1,2,3].first => 1 
[1,2,3][1..-1] => [2,3] 
[1] + [2,3]  => [1,2,3] 
+8

它不僅沒有用處,而且也沒有意義。 Car,cdr和cons與cons cell內在聯繫在一起。由於cons單元根本不涉及Ruby數組,因此任何此類方法都是錯誤的。 – Chuck 2009-10-05 23:45:28

2

我建議你閱讀Ruby的API爲Array。那裏有許多方法和操作員可以完全滿足你的需求。

http://www.ruby-doc.org/core/classes/Array.html

+0

儘管可以通過各種方式獲取數組的'cdr',包括'ary [1 ..- 1]',這與恕我直言不同,因爲它擁有一種完全符合需要的方法。 – Phrogz 2013-09-30 18:17:34

+0

這就是爲什麼Ruby有這個奇妙的設施來定義完全符合你需要的方法:'class Array; def cdr;自[1 ..- 1];結束;結束' – SFEley 2013-10-14 15:20:45

4
>> [1,2,3].drop 1 
=> [2, 3] 
>> [1,2,3].first 
=> 1 

當然,如你所知,這些都不是太接近Lisp的。真正的紅寶石相當於[1, [2, [3, nil]]]。你總是可以寫一個List類......或者找到一個地方。

Practical Ruby Projects的第8章被稱爲在Ruby中實現Lisp

10

這是怎麼你會在Ruby中實現Lisp的單鏈表:

class Object 
    def list? 
    false 
    end 
end 

class LispNilClass 
    include Enumerable 
    def each 
    end 

    def inspect 
    "lnil" 
    end 

    def cons(car) 
    Cell.new(car, self) 
    end 

    def list? 
    true 
    end 
end 

LispNil = LispNilClass.new 

class LispNilClass 
    private :initialize 
end 

class Cell 
    include Enumerable 

    attr_accessor :car, :cdr 

    def initialize(car, cdr) 
    @car = car 
    @cdr = cdr 
    end 

    def self.list(*elements) 
    if elements.empty? 
     LispNil 
    else 
     first, *rest = elements 
     Cell.new(first, list(*rest)) 
    end 
    end 

    def cons(new_car) 
    Cell.new(new_car, self) 
    end 

    def list? 
    cdr.list? 
    end 

    # Do not use this (or any Enumerable methods) on Cells that aren't lists 
    def each 
    yield car 
    cdr.each {|e| yield e} 
    end 

    def inspect 
    if list? 
     "(#{ to_a.join(", ") })" 
    else 
     "(#{car} . #{cdr})" 
    end 
    end 
end 

list = Cell.list(1, 2, 3) #=> (1, 2, 3) 
list.list? #=> true 
list.car #=> 1 
list.cdr #=> (2, 3) 
list.cdr.cdr.cdr #=> lnil 
list.cons(4) #=> (4, 1, 2, 3) 

notlist = Cell.new(1,2) #=> (1 . 2) 
notlist.list? #=> false 
notlist.car #=> 1 
notlist.cdr #=> 2 
notlist.cons(3) #=> (3 . (1 . 2)) 
+0

不錯........... – DigitalRoss 2009-10-06 03:44:20

7

半認真,如果你想在Ruby的利弊,CAR和CDR,你可以做有過之而無不及

 
def cons(x,y) 
    return lambda {|m| m.call(x,y)} 
end 

def car(z) 
    z.call(lambda {|p,q| p}) 
end 

def cdr(z) 
    z.call(lambda {|p,q| q}) 
end 

然後你就可以定義名單的程序,

 
def interval(low, high) 
    if (low > high) 
    return nil 
    else 
    return cons(low, interval(low + 1, high)) 
    end 
end 

def map(f, l) 
    if (l == nil) 
    return nil 
    else 
    cons(f.call(car(l)), map(f, cdr(l))) 
    end 
end 

def filter(p, l) 
    if (l == nil) 
    return nil 
    elsif (p.call(car(l))) 
    return cons(car(l), filter(p, cdr(l))) 
    else 
    return filter(p, cdr(l)) 
    end 
end 

def reduce(f, f0, l) 
    if (l == nil) 
    return f0 
    else 
    return f.call(car(l), reduce(f, f0, cdr(l))) 
    end 
end 

然後你可能會得到奇數平方的總和範圍在1到10之間的區域:

 
reduce(lambda {|x, y| x + y}, 
     0, 
     filter(lambda {|x| x % 2 == 1}, 
       map(lambda {|x| x * x}, 
        interval(1, 10)))) 
=> 165 
-1

不存在,但是如果需要,很容易編寫自己的文件。