
-----------------------------------
wtd
Sun Jan 29, 2006 4:56 pm

CLOS: Translations from Java and Ruby
-----------------------------------
CLOS: Translations from Java and Ruby

Let's look at the most basic classes we can, just to establish a baseline.

Java
class Foo {
}

Ruby
class Foo
end

CLOS
(defclass foo () 
    ())
    
This tutorial presumes familiarity with either Java or Ruby as they seem to be popular here, so I won't go into any detail explaining those code samples.

I do not, however, expect you to be familiar with CLOS, so that deserves some explanation.  The "defclass" macro clearly introduces a class called "foo".  The first set of parens would encompass any parent classes, if there were any.  The second would contain any slots, which we'll see as the tutorial progresses.

Instance variables, contruction and slots

Let's store some information.

Java
class Foo {
    private int bar;
    
    public Foo() {
       this.bar = 42;
    }
    
    public Foo(int bar) {
       this.bar = bar;
    }
}

Foo myFoo = new Foo();
Foo myOtherFoo = new Foo(27);

Ruby
class Foo
    def initialize(bar = 42)
        @bar = bar
    end
end

my_foo = Foo.new
my_other_foo = Foo.new(27)

CLOS
(defclass foo () 
    ((bar :initarg  :bar
          :initform 42)))
          
(setf *my-foo* (make-instance 'foo))
(setf *my-other-foo* (make-instance 'foo :bar 27))

So, what have we accomplished?  We've created "bar" within the Foo class for storing information.  We've specified that it should have a default value of 42.

Now, here's the thing... with CLOS we didn't have to write any methods to manipulate the data.  We just specified that the slot's initial value should be 42.  We didn't write the "constructor".  We just provided information about the slot.  Regardless of what you think about the syntax, there's a deep and profound beauty to this concept.

Let's write a method

Java
class Foo {
    private int bar;
    
    public Foo() {
        this.bar = 42;
    }
    
    public Foo(int bar) {
        this.bar = bar;
    }
    
    public int getBar() {
        return bar;
    }
    
    public void writeBarTimes(String msg) {
        for (int i = 0; i < bar; i++) {
            System.out.println(msg);
        }
    }
}

Foo myFoo = new Foo();
myFoo.writeBarTimes("Hello");

Ruby
class Foo
    attr_reader :bar

    def initialize(bar = 42)
        @bar = bar
    end
    
    def write_bar_times(msg)
        bar.times do
           puts msg
        end
    end
end

my_foo = Foo.new
my_foo.write_bar_times("Hello")

CLOS
(defclass foo () 
    ((bar :initarg  :bar
          :initform 42
          :reader   get-bar)))
          
(defmethod write-bar-times ((this-foo foo) msg)
    (loop repeat (get-bar this-foo) do
        (format t "~A~&" msg)))
          
(setf *my-foo* (make-instance 'foo))
(write-bar-times *my-foo* "Hello")

More to come

Keep checking back for updates.  :)
