Hi, Mikera.
Thanks for the feedback, it was a very interesting read.
Nice, I have been looking for something like this to experiment with.
Glad to see someone else who likes to experiment with weird code :P
However, I must admit that I made it mainly as a toy project, with no
serious intent for actually using it (I actually try to avoid OO as much as
possible, since I don't see it as a good solution to most problems). I just
wanted to see how feasible it was to implement an OO system on top of
functions. However, reading what you wrote gave me some ideas, so I might
work on it more and see where it takes me. The implementation itself has
only ~70 LoC, so it turned out to be pretty easy to do.
Suggestions on syntax: It would be much nicer to use and more idiomatic
if the method name came first, e.g.
(method some-object arg1 arg2)
The idea was for objects to be functions, which means they have to go
first. Having the methods be keywords and not other functions also gave it
a sort of message-passing feel that is kinda nice.
This would bring many benefits: you could use the standard "->" syntax,
you can "apply" a method, it will fit much better when composed with
Clojure library functions etc.
Being able to use Clojure's "->" macro would have been real nice, but
having the objects be functions made it impossible. It's just a sad reality
I'll have to live with.
You could also potentially use any associative data structure as your
object type.
There are only two alternatives to regular Clojure maps when it comes to
associative data structures. One is vectors, but I'm not sure what the
semantics of using vectors as the storage unit would be. The other is
allowing custom "map-like" datatypes made by users. However, one fear I had
was allowing people to use mutable implementations (like a KV cache, for
example), which would have messed up the functional feel of the library.
One idea I had was also to create an object datatype that implemented the
interfaces to behave like a map and a function. That way people would have
been able to use assoc & dissoc, for example. However, wanting to keep
things minimal and to rely only on regular functions, I discarded that
option.
You could also potentially have special handling for null object values,
default implementations in case of missing methods etc.
The idea for the missing methods is quite nice. I'm thinking maybe a way
could be added to the library to create hooks into several "life-cycle
events" of the objects.
You could have hooks for calling functions:
+ That way you could implement before|after|around mixin functionality.
+ You could also have method-missing code to work by doing that.
You could have hooks for reading/writing attributes:
+ That would you could have setter-like validation of changes.
+ You could also implement virtual-slots with it, reading from fields
that are actually calculated on-the-fly.
This suggests to me that it would be a better design if each method was
defined as a function that looked up the specific implementation in the
prototype object and called it.
Obviously, this means that you need to explicitly declare prototype methods.
But I think this is a good idea anyway: it ensures a bit more discipline
and testability (which is often the biggest problem in prototype-based
systems.....)
That is something that can certainly be done, but I'm not sure if the
library should implement it.
What I mean by that is this: the implementation is meant to provide the
bare minimum you need to build everything else you need on top.
That functionality can easily be built on top without needing to modify the
OO system itself; so although it would be cool to have that, I don't think
the library should concern itself with providing it.
Regarding the discipline and testability: I really like to strive towards
those two things, but thinking about incorporating those changes kinda
makes me feel like we're back in the class-based OO world. Not because we
have actual classes around, but because providing so much specification
code feels like we have supplanted classes with some sort of implicit
quasi-class-like OO specification, and I'm not sure if that would play so
well with the dynamicity that the library strives to achieve.
--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to
clojure@googlegroups.comNote that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+
unsubscribe@googlegroups.comFor more options, visit this group at
http://groups.google.com/group/clojure?hl=en---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscribe@googlegroups.com.
For more options, visit
https://groups.google.com/groups/opt_out.