GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Description: Lispy is sexpy Ruby

Home

(kind_of? (meta-class Ruby) Lisp)

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

Why?

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 + "!" 
          end
      end
      HelloWorld.new.salute("world")
   

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.

Literals

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

Arrays

Don’t use commas, just separate with white space

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

Hashes

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
         end
     end
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.

Quoting

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.

Last edited by vic, 7 months ago
Versions: