a practical Lisp in Ruby

Discussion in 'Ruby' started by Elliott Hird, Mar 1, 2008.

  1. Elliott Hird

    Elliott Hird Guest

    Hi! I've been working on a Lisp interpreter in Ruby that is fully
    integrated (I mean -- fully. The aim is to have basically nothing
    specific to the interpreter and use Ruby for everything. Basic rule of
    thumb: you should be able to use it to write a Rails app with no extra
    pain than in Ruby.)

    Some examples:

    '(1 2 3) => (1 2 3)
    [1 2 3] => [1 2 3]
    ([] empty?) => true
    (puts (if ([] empty?) "hello world" "oh no")) => hello world

    Now, I hope to have some code released Real Soon Now (it really isn't
    usable enough yet; needs some reworking). But I'd like the Ruby
    community's opinion on some few things, to try and make it as Ruby-ish
    as possible. So, dump of things I've thought about:

    - should # be used as a comment marker (instead of ;)? it might get in
    the way of *something*, lisp dialects tend to use it a lot, but #\c
    will probably be ?c, #t/#f is true/false, and #(...) is [...] so I'm
    not sure.

    - should 'a be ruby's :a? that could mess up pretty printing, e.g.:
    '(a b c) => :)a :b :c)
    if 'a is something other than :a, what should
    it be? a subclass of Symbol that just overrides pretty-printing, i
    guess. and then :a would be ruby's :a.

    - syntax for dicts? if we take the above idea, I think something like:
    {:a 2 :b 3} => {:a => 2, :b => 3}
    would be nice, but again there's the problem that pretty-printing loses out.
    however I don't think that Ruby's syntax should be re-used directly, because
    it's not lisp-like.

    - how to call out to ruby. what happens if you pass a list to a ruby function?
    I could recursively translate them to arrays, but that's expensive and
    if you're calling out to something that wants to directly use the object
    or is one of the functions that doesn't care what type its object is,
    it might not even be expected behaviour. also, should i translate a_b to a-b?
    vise-versa?

    - on a similar note, what class is (lambda (x) x)? if a Proc I have to
    have a trampoline in the Proc, which isn't nice. a subclass of Proc?

    - how to handle blocks. some ideas:
    ([1 2 3] map (lambda (x) (+ x 1)))
    that means I have to do arity stuff, and presents a problem -- what if
    'map' there was variadic? are we passing a function, or a block?
    ([1 2 3] map (do (x) (+ x 1)))
    here 'do' creates something internally treated as a block. again the
    variadic problem, relating to my "what if the func/method doesn't care
    about the type it gets"?
    ([1 2 3] map do (x) (+ x 1))
    this is a little bit hard to read, but unambigious. of course, now you
    can't use "do" in most places. a multiline example of this:
    ([0 1 2 3 4 5] map do (x)
    (if (= (% x 2) 0)
    (+ x 5)
    (- x 4)))
    this is my preferred syntax at the moment, actually. maybe i could hijack
    {...} somehow (don't really like that idea).

    - (def (func ...) ...) or (def func (...) ...)? the former seems more rubyish
    to me, i guess. (def (foo) ...) instead of (def foo () ...).

    - this thing:=> 4
    since this thing will emulate a Lisp-1 (basically), how should this be
    handled? maybe in the same way.

    - and closely linked to that: since a 0-arg function is used often in Ruby
    in place of a variable (but -- mostly in a method, where this would be
    (obj foo) so it wouldn't be a problem). you'd have to do (foo) currently,
    which would differenciate it from foo.

    - also related: watch this imaginary session in the Lisp REPL=> "you can't call a Fixnum!" or 4?

    this clashes with Lisp-1-ness, certainly.

    Anyway, that's the end of this long post for now. Feel free to ignore
    my ramblings, but to leave, here's a few code examples that don't actually work
    right now and may look completely different when they do :)

    ;; Output "I love Ruby"
    (def say "I love Ruby")
    (puts say)

    ;; Output "I *LOVE* RUBY"
    (set! (say "love") "*love*") ;; set! name?
    (puts (say upcase))

    ;; Output "I *love* Ruby" five times
    (5 times do (puts say))

    and the second:

    (class Numeric
    (def (plus x)
    (self + x)
    ;; or (the same, but variadic)
    (+ self x)))

    Well, OK. Have a third.

    (def search-engines
    (%w[Google Yahoo MSN] map do (engine)
    (+ "http://www." (engine downcase) ".com")))

    -ehird
     
    Elliott Hird, Mar 1, 2008
    #1
    1. Advertisements

  2. Elliott Hird

    Kyle Brooks Guest

    This is a VERY interesting idea, but why do you want to do this?

    - Kyle

     
    Kyle Brooks, Mar 1, 2008
    #2
    1. Advertisements

  3. Elliott Hird

    Elliott Hird Guest

    For a start - because it can be done ;-).

    For another - because I want to see what happens when you combine Lisp
    awesomeness like macros & such with Ruby's elegance and libraries. I
    am expecting an explosion of some sort.

    Who knows? Maybe it'll target YARV one day, and be a first-class
    citizen, just like Ruby itself.

    -ehird
     
    Elliott Hird, Mar 1, 2008
    #3
  4. Elliott Hird

    James Britt Guest

    Elliott Hird wrote:
    ome sort.
    Perhaps combined with Rubinious you really could have Lisp-like macros.
     
    James Britt, Mar 1, 2008
    #4
  5. Elliott Hird

    Elliott Hird Guest

    You mean, in Ruby itself? That would be crazy awesome. :)

    But they will probably be ugly. Ruby parse trees aren't as nice as Lisp ones ;)
     
    Elliott Hird, Mar 1, 2008
    #5


  6. Elliot-

    You may want to look at these two projects:

    http://chaosforge.org/taw/rlisp/

    http://bus-scheme.rubyforge.org/

    rlisp is a lisp to ruby compiler with nice lisp -> ruby integration
    that solves most of the problems you are asking about. Bus Scheme is
    a scheme written in ruby with ruby integration.

    Rlisp is more complete but I prefer scheme to lisp myself so bus
    scheme is pretty interesting, bus scheme already runs on rubinius too ;)

    Cheers-
    - Ezra Zygmuntowicz
    -- Founder & Software Architect
    --
    -- EngineYard.com
     
    Ezra Zygmuntowicz, Mar 1, 2008
    #6
  7. Elliott Hird

    Elliott Hird Guest

    I've seen rlisp briefly and Bus Scheme too. Bus Scheme isn't really
    that integrated; more Scheme than Ruby, IMO. RLisp is quite nice but
    not quite perfect, IMO -- the philosophy's quite different.

    My idea is a Ruby Lisp, really, not a Lisp integrated with Ruby. :)

    -ehird
     
    Elliott Hird, Mar 1, 2008
    #7
  8. Elliott Hird

    Brian Adkins Guest

    Bummer. I work from my home typically, so I don't think I can
    contribute to Bus Scheme ;)
     
    Brian Adkins, Mar 2, 2008
    #8
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.