2010-08-09 67 views
5

我已經能夠找到:書面紅寶石(即外部DSL)Lisp作爲內部Ruby DSL?

http://onestepback.org/index.cgi/Tech/Ruby/LispInRuby.red

B)序言作爲Ruby DSL

http://www.kdedevelopers.org/node/2369

一)Lisp的口譯

c)討論Ruby「as」Lisp

http://www.randomhacks.net/articles/2005/12/03/why-ruby-is-an-acceptable-lisp

但奇怪的是,我實際上找不到Lisp的內部實現,就像Prolog的實現一樣。我只是不夠格力,還是沒有人發佈過這樣的想法?

或者它可能是一個不能做到這一點在Ruby?

+2

Prolog的東西看起來更像'草圖',而不是實際的實現。你爲什麼要在Ruby中使用Lisp? Ruby可能是實現其他語言的最差語言之一。有些情況下Ruby比典型的Lisp慢百倍:http://shootout.alioth.debian.org/u32/benchmark.php?test=all&lang = yarv&lang2 = sbcl - 現在想象一下運行在Ruby之上的Lisp的緩慢。 Lisp也不是DSL,而是一系列完全一般的編程語言。 – 2010-08-09 21:05:45

+0

這與「外部DSL」有何不同? 「Prolog作爲Ruby DSL」稍微改變了Prolog的語法以在Ruby中工作。 「在Ruby中編寫的Lisp解釋器」還允許你在Ruby中編寫具有稍微不同語法的Lisp,例如'[]'而不是'()'和':lambda'而不是'lambda'。你還想要什麼? – Ken 2010-08-09 21:10:15

+0

這純粹是作爲一種學習練習。我發現Lisp作爲一種語言引人入勝,但是很痛苦。我知道可以在Lisp裏面實現Lisp(我在20多年前就已經完成了!)。推測在Ruby中實現Lisp同樣很容易,只需要簡單得多的語法 - 這會讓我更容易理解發生了什麼。 – 2010-08-09 21:38:42

回答

2

下面是Lisp的程序員手冊第13頁的Lisp解釋了Ruby代碼:

# Kernel Extensions to support Lisp 
class Object 
    def lisp_string 
    to_s 
    end 
end 

class NilClass 
    def lisp_string 
    "nil" 
    end 
end 

class Array 
    # Convert an Array into an S-expression (i.e. linked list). 
    # Subarrays are converted as well. 
    def sexp 
    result = nil 
    reverse.each do |item| 
     item = item.sexp if item.respond_to?(:sexp) 
     result = cons(item, result) 
    end 
    result 
    end 
end 

# The Basic Lisp Cons cell data structures. Cons cells consist of a 
# head and a tail. 
class Cons 
    attr_reader :head, :tail 

    def initialize(head, tail) 
    @head, @tail = head, tail 
    end 

    def ==(other) 
    return false unless other.class == Cons 
    return true if self.object_id == other.object_id 
    return car(self) == car(other) && cdr(self) == cdr(other) 
    end 

    # Convert the lisp expression to a string. 
    def lisp_string 
    e = self 
    result = "(" 
    while e 
     if e.class != Cons 
     result << ". " << e.lisp_string 
     e = nil 
     else 
     result << car(e).lisp_string 
     e = cdr(e) 
     result << " " if e 
     end 
    end 
    result << ")" 
    result 
    end 
end 

    # Lisp Primitive Functions. 

    # It is an atom if it is not a cons cell. 
    def atom?(a) 
    a.class != Cons 
    end 

    # Get the head of a list. 
    def car(e) 
    e.head 
    end 

    # Get the tail of a list. 
    def cdr(e) 
    e.tail 
    end 

    # Construct a new list from a head and a tail. 
    def cons(h,t) 
    Cons.new(h,t) 
    end 

    # Here is the guts of the Lisp interpreter. Apply and eval work 
    # together to interpret the S-expression. These definitions are taken 
    # directly from page 13 of the Lisp 1.5 Programmer's Manual. 

    def apply(fn, x, a) 
    if atom?(fn) 
     case fn 
     when :car then caar(x) 
     when :cdr then cdar(x) 
     when :cons then cons(car(x), cadr(x)) 
     when :atom then atom?(car(x)) 
     when :eq then car(x) == cadr(x) 
     else 
     apply(eval(fn,a), x, a) 
     end 
    elsif car(fn) == :lambda 
     eval(caddr(fn), pairlis(cadr(fn), x, a)) 
    elsif car(fn) == :label 
     apply(caddr(fn), x, cons(cons(cadr(fn), caddr(fn)), a)) 
    end 
    end 

    def eval(e,a) 
    if atom?(e) 
     cdr(assoc(e,a)) 
    elsif atom?(car(e)) 
     if car(e) == :quote 
     cadr(e) 
     elsif car(e) == :cond 
     evcon(cdr(e),a) 
     else 
     apply(car(e), evlis(cdr(e), a), a) 
     end 
    else 
     apply(car(e), evlis(cdr(e), a), a) 
    end 
    end 

    # And now some utility functions used by apply and eval. These are 
    # also given in the Lisp 1.5 Programmer's Manual. 

    def evcon(c,a) 
    if eval(caar(c), a) 
     eval(cadar(c), a) 
    else 
     evcon(cdr(c), a) 
    end 
    end 

    def evlis(m, a) 
    if m.nil? 
     nil 
    else 
     cons(eval(car(m),a), evlis(cdr(m), a)) 
    end 
    end 

    def assoc(a, e) 
    if e.nil? 
     fail "#{a.inspect} not bound" 
    elsif a == caar(e) 
     car(e) 
    else 
     assoc(a, cdr(e)) 
    end 
    end 

    def pairlis(vars, vals, a) 
    while vars && vals 
     a = cons(cons(car(vars), car(vals)), a) 
     vars = cdr(vars) 
     vals = cdr(vals) 
    end 
    a 
    end 

    # Handy lisp utility functions built on car and cdr. 

    def caar(e) 
    car(car(e)) 
    end 

    def cadr(e) 
    car(cdr(e)) 
    end 

    def caddr(e) 
    car(cdr(cdr(e))) 
    end 

    def cdar(e) 
    cdr(car(e)) 
    end 

    def cadar(e) 
    car(cdr(car(e))) 
    end 

所以我們說你有以下Lisp代碼:

(defun reverse (list) 
    (rev-shift list nil)) 

(defun rev-shift (list result) 
    (cond ((null list) result) 
    (t (rev-shift (cdr list) (cons (car list) result))))) 

你可以在DSL中呈現爲:

require 'lisp' 

    # Create an environment where the reverse, rev_shift and null 
    # functions are bound to an appropriate identifier. 

    env = [ 
    cons(:rev_shift, 
     [:lambda, [:list, :result], 
     [:cond, 
      [[:null, :list], :result], 
      [:t, [:rev_shift, [:cdr, :list], 
       [:cons, [:car, :list], :result]]]]].sexp), 
    cons(:reverse, 
     [:lambda, [:list], [:rev_shift, :list, nil]].sexp), 
    cons(:null, [:lambda, [:e], [:eq, :e, nil]].sexp), 
    cons(:t, true), 
    cons(nil, nil) 
    ].sexp 

    # Evaluate an S-Expression and print the result 

    exp = [:reverse, [:quote, [:a, :b, :c, :d, :e]]].sexp 

    puts "EVAL: #{exp.lisp_string}" 
    puts " => #{eval(exp,env).lisp_string}" 

(解釋器和示例的原始源can be found here。)

更新:剛纔意識到你在你的問題中提到了這個解決方案。