| For those of you who don't know, JavaScript uses prototypes rather than classes like most popular languages. What this boils down to is that class and instance is the same thing. Rather than creating a class that inherits from another class, and then creating an instance, you simply create an object that inherits directly from another object. In my opinion, this unification of class and instance leads to a simpler and more light-weight inheritance system while still retaining the power of classes. Although Arc is not an OO language, I think prototypes can have their uses, for instance to save memory in certain situations. How it works is: when looking up a property, if the property is not found, it then checks it's parent. This is applied recursively until either the property is found, or not found. I implemented a "clone" macro that does just that. Here's an example: (= a (clone nil x "foo"))
(= b (clone a y "bar"))
(= c (clone b z "qux"))
a!x -> "foo"
a!y -> nil
a!z -> nil
b!x -> "foo"
b!y -> "bar"
b!z -> nil
c!x -> "foo"
c!y -> "bar"
c!z -> "qux"
(clone nil) is the same as (obj) except that "clone" is probably slower. Now, it's important to understand that this does not copy the object. Observe: (= b!x "changed")
a!x -> "foo"
b!x -> "changed"
c!x -> "changed"
By changing a property on "b", it caused the property to be changed on "c" as well, because it inherits from "b". Here is the entire implementation. It uses aw's extend macro, which makes it trivial to allow for different data-types in a call to "=": ;; http://awwx.ws/extend
(extend sref (x v n) (isa x 'fn) (x n v))
(mac clone (p . args)
(w/uniq new
`(let ,new (obj ,@args)
(fn (n . args)
(if args (= (,new n) (car args))
(or (,new n) (and ,p (,p n))))))))
As a consequence of extending sref, functions can now be used as setters when they are assigned to with "=". What does this mean? Perhaps an example will help: (def foo (name value)
(prn:list name value))
(= foo!x "bar") -> (x bar)
As you can see, the function "foo" is called and is given both the variable that is being assigned to, and the value. This is the secret to making "clone" work. Can anybody think of any situations where this overloading would cause problems?P.S. This simple system does not handle types correctly, since "clone" returns a function. So for instance, the "keys" function won't work. I'm not sure how to get that working, but perhaps this simple inheritance is useful in some circumstances. Also, supplying a default parameter causes the value to be written: (a 'x 10) This is an inconsistency with (obj), which does not write the value. I may be able to fix this. P.P.S. I was surprised by how trivial it was to both extend sref and implement clone. Arc's expressive power seems quite high, to me. |