vic edited this page Sep 12, 2010 · 5 revisions
Clone this wiki locally

(kind_of? (meta-class Ruby) Lisp)

Lispy can be seen as a lisp-like language resembling Ruby’s sexp or Ruby with lisp syntax.


We all love ruby and it’s beautiful syntax. That’s not the problem, actually Lispy goal is to
serve as an easy way to modify a ruby s-expression. Ruby programs that modify/produce Ruby programs.
This would allow to have a macro system on most ruby implementations.

Object oriented (It’s just Ruby)

The two following code fragments are equivalent:

      class HelloWorld
          def salute(person)
              puts "Hello" + person.upcase + "!"

Is compiled into

      (class HelloWorld
          (def salute (person)
               (:puts (+ "Hello " (upcase person) "!"))
      (salute (new HelloWorld)  "world")

See ObjectOriented for more info on how lispy interprets method calls.


Because Lispy is just ruby most of the ruby literals are the same except:


Don’t use commas, just separate with white space

[a b c] is the same that ruby’s : [a, b, c]


Use pairs as associations.

{ (a b) (c d) } is the same that ruby’s: { a => b, c => d}

Block iteration

Instead of:

[1, 2, 3].each { |num| num.succ }

The lispy syntax is:

(do (num) (each [1 2 3]) (succ num) )

The general form is:

(do <arguments> <expression> <body...>)

If expression yields a partial application (se bellow) the do form will
return another partial application waiting to fulfill its arguments.
When all arguments are in place, the evaluation takes place and the body
is seen as the block passed to the each method.

It’s also Lisp

    ;; in ruby: Kernel.send("pu" + "ts", "Hello", "World")
    (. Kernel (+ "pu" "ts) "Hello" "World")  
     (|num| (downto 5 1) (:puts num)) ;; same than 5.downto(1) { |num| puts num }

     (= (a, b) 1 2) ;; a, b = 1, 2

     (name= self "lispy") ;; self.name = "lispy"

     ;; { 1 => 2, 3 => 4}.each_pair { |key, val| puts key + val }
     (|key val| (each_pair { (1 2) (3 4) }) (:puts (+ key val)))

Partial applications .

Suppose you have a method:

     class Number 
         def sum(a, b)
             a + b
In lispy a partial application on an instance num of Number would be @ (sum num 1) ;; returns just a lambda expecting another argument @

The . form, returns a partial application it the invoked method expects more arguments.

@ (. num :sum 1)@

The :sum argument could actually be an expression determining the method to be called.


The following expression result is the list (+ 1 2) not the result of applying 1 + 2

'(+ 1 2)

Special Forms

In the following example, expr2 is only evaluated if expr1 evaluated to non-true and if expr2 itself
was non-true expr3 is evaluated and its value is the expression value.

(and expr1 expr2 expr3)

Special forms are defined with the defmacro form.

       (defmacro unless (a b c)  `(if ,(not a) ,b ,c) )
       (unless (has_money?) (work :more) (buy (+ "ice" "cream")))

The buy method is only applied if self has money.