I've always liked the way that Javascript treats objects; they're just hashtables, and object methods are simply functions in that hashtable where the special value "this" refers to the hashtable. For example, if we wanted a simple Person class, we'd say: function Person(first, last, age) {
return {
first: first,
last: last,
age: age,
full: function() {
return this.first + " " + this.last;
},
until: function(year) {
return year - this.age;
}
}
}
p = new Person("Eli", "Courtwright", 25);
p.full();
p.until(30);
What I most like is that we can call methods on p instead of defining and calling global functions and passing p as a parameter (and thus not having to worry about name collisions).For example, in Arc I'd do the same thing by saying (= p (obj
first "Eli"
last "Courtwright"
age 25))
(def person-full (p) (string p!first " " p!last))
(def person-until (p year) (- year p!age))
(person-full p)
(person-until p 30)
I basically need to prefix my global functions with "person-" to avoid name collisions and so that it's clear what those functions are supposed to act upon. This isn't especially onerous, and maybe I'm being silly by letting this bother me, but I just really prefer "p.until(30)" to "(person-until p 30)". It both seems more aesthetically pleasing and easier to read.So if we want to be able to write code like "(p!until 30)" then all we need is a macro: (mac new params
`(let this (table)
,@(map (fn ((name val)) `(= (this ',name) ,val))
(pair params))
this))
This basically gives us Javascript-style objects. We can use them like so: (def Person (first last age)
(new
first first
last last
age age
full (fn () (string this!first " " this!last))
until (fn (year) (- year this!age))))
(= p (Person "Eli" "Courtwright" 25))
(p!full)
(p!until 30)
This doesn't give us inheritance or many other features of "object-oriented" programming, but I still like it for letting me say "(p!until 30)" instead of "(person-until p 30)".What do the more experienced Lispers out there think? Am I just having a beginner's reaction to Lisp, and should I just deal with "(person-until p 30)" which a module system might make more clear anyway? Or do many of you like the way that the "new" macro makes this code look? |